Revert "feat(skills): support skills-sh install references (#112517)" (#112531)

This reverts commit 7c353b7436.
This commit is contained in:
Patrick Erichsen
2026-07-21 22:37:50 -07:00
committed by GitHub
parent 58c138374d
commit a691eb7372
9 changed files with 11 additions and 287 deletions
-5
View File
@@ -22,7 +22,6 @@ Two command-line surfaces talk to ClawHub:
openclaw skills search "calendar"
openclaw skills install @owner/<slug>
openclaw skills install @owner/<slug> --version <version> --global
openclaw skills install skills-sh:<owner>/<repo>/<slug>
openclaw skills update @owner/<slug>
openclaw skills update --all --acknowledge-clawhub-risk
openclaw skills verify @owner/<slug> --card
@@ -40,10 +39,6 @@ explicit `clawhub:` prefix to force ClawHub resolution over npm, git, or a
local path. Full flag reference: [`openclaw skills`](/cli/skills) and
[`openclaw plugins`](/cli/plugins).
`skills-sh:` is a discovery reference only. OpenClaw sends it to ClawHub and
installs the security-approved, commit-pinned GitHub source returned by
ClawHub; it never downloads skill content from skills.sh directly.
### Release trust
OpenClaw checks a release's ClawHub trust state before downloading it, for
+3 -7
View File
@@ -27,7 +27,6 @@ openclaw skills search "calendar"
openclaw skills search --limit 20 --json
openclaw skills install @owner/<slug>
openclaw skills install @owner/<slug> --version <version>
openclaw skills install skills-sh:<owner>/<repo>/<slug>
openclaw skills install git:owner/repo
openclaw skills install git:owner/repo@main
openclaw skills install ./path/to/skill --as custom-name
@@ -70,11 +69,8 @@ openclaw skills workshop quarantine <proposal-id> --reason "Needs security revie
```
`search`, `update`, and `verify` use ClawHub directly. `install @owner/<slug>`
installs a ClawHub skill. `install skills-sh:<owner>/<repo>/<slug>` asks
ClawHub to resolve that discovery reference to a security-approved,
commit-pinned GitHub source; OpenClaw does not download from skills.sh.
`install git:owner/repo[@ref]` clones a Git skill, and `install ./path` copies
a local skill directory. By default, `install`,
installs a ClawHub skill, `install git:owner/repo[@ref]` clones a Git skill,
and `install ./path` copies a local skill directory. By default, `install`,
`update`, and `verify` target the active workspace `skills/` directory; with
`--global`, they target the shared managed skills directory. `list`/`info`/`check`
still inspect the local skills visible to the current workspace and config.
@@ -101,7 +97,7 @@ Notes:
| `install git:owner/repo[@ref]` | Installs a Git skill. Branch refs may contain slashes, such as `git:owner/repo@feature/foo`. |
| `install ./path/to/skill` | Installs a local directory whose root contains `SKILL.md`. |
| `install --as <slug>` | Overrides the inferred slug for Git and local directory installs. |
| `install --version <version>` | Applies to native ClawHub skill refs, not `skills-sh:` refs; ClawHub selects the approved GitHub commit for those references. |
| `install --version <version>` | Applies only to ClawHub skill refs. |
| `install --force` | Overwrites an existing workspace skill folder for the same slug. |
| `install/update --force-install` | Installs a pending GitHub-backed ClawHub skill before ClawHub's scan completes. |
| `--global` | Targets the shared managed skills directory; cannot combine with `--agent <id>`. |
-1
View File
@@ -164,7 +164,6 @@ publish and sync.
| Action | Command |
| ---------------------------------- | ------------------------------------------------------ |
| Install a skill into the workspace | `openclaw skills install @owner/<slug>` |
| Install a skills.sh discovery ref | `openclaw skills install skills-sh:owner/repo/slug` |
| Install from a Git repository | `openclaw skills install git:owner/repo@ref` |
| Install a local skill directory | `openclaw skills install ./path/to/skill --as my-tool` |
| Install for all local agents | `openclaw skills install @owner/<slug> --global` |
-25
View File
@@ -488,31 +488,6 @@ describe("skills cli commands", () => {
).toBe(true);
});
it("routes skills-sh refs through ClawHub without translating them", async () => {
const reference = "skills-sh:openclaw/skills/weather";
installSkillFromClawHubMock.mockResolvedValue({
ok: true,
slug: "weather",
version: "a".repeat(40),
targetDir: "/tmp/workspace/skills/weather",
});
await runCommand(["skills", "install", reference]);
expect(mockFirstObjectArg(installSkillFromClawHubMock).slug).toBe(reference);
expect(installSkillFromSourceMock).not.toHaveBeenCalled();
});
it("rejects --version for skills-sh refs", async () => {
await expect(
runCommand(["skills", "install", "skills-sh:openclaw/skills/weather", "--version", "1.2.3"]),
).rejects.toThrow("__exit__:1");
expect(runtimeErrors).toContain("--version is not supported for skills-sh references.");
expect(installSkillFromClawHubMock).not.toHaveBeenCalled();
expect(installSkillFromSourceMock).not.toHaveBeenCalled();
});
it("documents owner-qualified ClawHub install refs in command help", () => {
const skillsCommand = createProgram().commands.find((command) => command.name() === "skills");
const installCommand = skillsCommand?.commands.find((command) => command.name() === "install");
+2 -13
View File
@@ -454,7 +454,7 @@ export function registerSkillsCli(program: Command) {
.description("Install a skill from ClawHub, git, or a local directory")
.argument(
"<skill-ref>",
"ClawHub skill ref (@owner/slug or skills-sh:owner/repo/slug), git:<repo>, or local skill directory",
"ClawHub skill ref (@owner/slug), git:<repo>, or local skill directory",
)
.option("--version <version>", "Install a specific version")
.option("--force", "Overwrite an existing workspace skill", false)
@@ -471,10 +471,7 @@ export function registerSkillsCli(program: Command) {
.option("--global", "Install into the shared managed skills directory", false)
.option("--agent <id>", "Target agent workspace (defaults to cwd-inferred, then default agent)")
.option("--as <slug>", "Install a git/local skill under this slug")
.addHelpText(
"after",
"\nExamples:\n openclaw skills install @owner/weather\n openclaw skills install skills-sh:owner/repo/weather\n",
)
.addHelpText("after", "\nExamples:\n openclaw skills install @owner/weather\n")
.action(
async (
slug: string,
@@ -528,11 +525,6 @@ export function registerSkillsCli(program: Command) {
defaultRuntime.exit(1);
return;
}
if (slug.trim().startsWith("skills-sh:") && opts.version) {
defaultRuntime.error("--version is not supported for skills-sh references.");
defaultRuntime.exit(1);
return;
}
const result = await installSkillFromClawHub({
workspaceDir,
slug,
@@ -693,9 +685,6 @@ export function registerSkillsCli(program: Command) {
const verification = await fetchClawHubSkillVerification({
slug: target.slug,
...(target.ownerHandle ? { ownerHandle: target.ownerHandle } : {}),
...(target.requestedReference
? { requestedReference: target.requestedReference }
: {}),
version: target.version,
tag: target.tag,
baseUrl: target.baseUrl,
-55
View File
@@ -433,29 +433,6 @@ describe("clawhub helpers", () => {
expect(fetchImpl).not.toHaveBeenCalled();
});
it("preserves skills-sh references in install telemetry", async () => {
let body: unknown;
await reportClawHubSkillInstallTelemetry({
token: "token-123",
slug: "weather",
version: "a".repeat(40),
requestedReference: "skills-sh:openclaw/skills/weather",
fetchImpl: async (_input, init) => {
expect(typeof init?.body).toBe("string");
body = JSON.parse(init?.body as string);
return new Response(null, { status: 200 });
},
});
expect(body).toMatchObject({
event: "install",
slug: "weather",
version: "a".repeat(40),
reference: "skills-sh:openclaw/skills/weather",
});
});
it("preserves the configured ClawHub base URL path prefix", async () => {
process.env.OPENCLAW_CLAWHUB_URL = "https://internal.example.com/clawhub";
let requestedUrl = "";
@@ -566,38 +543,6 @@ describe("clawhub helpers", () => {
expect(url.searchParams.get("ownerHandle")).toBe("demo-owner");
});
it("sends skills-sh references to the ClawHub install resolver", async () => {
let requestedUrl = "";
const reference = "skills-sh:openclaw/skills/weather";
await fetchClawHubSkillInstallResolution({
slug: "weather",
requestedReference: reference,
fetchImpl: async (input) => {
requestedUrl = input instanceof Request ? input.url : String(input);
return new Response(
JSON.stringify({
ok: true,
slug: "weather",
installKind: "github",
github: {
repo: "openclaw/skills",
path: "skills/weather",
commit: "a".repeat(40),
contentHash: "sha256:approved",
sourceUrl: "https://github.com/openclaw/skills",
},
}),
{ headers: { "content-type": "application/json" } },
);
},
});
const url = new URL(requestedUrl);
expect(url.pathname).toBe("/api/v1/skills/weather/install");
expect(url.searchParams.get("reference")).toBe(reference);
});
it("fetches skill verification reports and lets version take precedence over tag", async () => {
let requestedUrl = "";
const envelope = {
+1 -9
View File
@@ -1234,7 +1234,6 @@ export async function fetchClawHubSkillDetail(params: {
export async function fetchClawHubSkillInstallResolution(params: {
slug: string;
ownerHandle?: string;
requestedReference?: string;
baseUrl?: string;
token?: string;
timeoutMs?: number;
@@ -1249,7 +1248,6 @@ export async function fetchClawHubSkillInstallResolution(params: {
fetchImpl: params.fetchImpl,
search: {
ownerHandle: params.ownerHandle,
reference: params.requestedReference,
forceInstall: params.forceInstall ? "1" : undefined,
},
});
@@ -1267,7 +1265,6 @@ export async function fetchClawHubSkillInstallResolution(params: {
export async function fetchClawHubSkillVerification(params: {
slug: string;
ownerHandle?: string;
requestedReference?: string;
version?: string;
tag?: string;
baseUrl?: string;
@@ -1281,10 +1278,7 @@ export async function fetchClawHubSkillVerification(params: {
token: params.token,
timeoutMs: params.timeoutMs,
fetchImpl: params.fetchImpl,
search: {
...buildVersionOrTagSearch(params),
...(params.requestedReference ? { reference: params.requestedReference } : {}),
},
search: buildVersionOrTagSearch(params),
});
}
@@ -1605,7 +1599,6 @@ export async function reportClawHubSkillInstallTelemetry(params: {
token?: string;
slug: string;
ownerHandle?: string;
requestedReference?: string;
version?: string | null;
timeoutMs?: number;
fetchImpl?: FetchLike;
@@ -1630,7 +1623,6 @@ export async function reportClawHubSkillInstallTelemetry(params: {
event: "install",
slug,
...(params.ownerHandle ? { ownerHandle: params.ownerHandle } : {}),
...(params.requestedReference ? { reference: params.requestedReference } : {}),
version: params.version ?? undefined,
},
});
-101
View File
@@ -129,7 +129,6 @@ async function writeClawHubOriginFixture(params: {
slug: string;
originSlug?: string;
ownerHandle?: string;
requestedReference?: string;
registry?: string;
installedVersion?: string;
installedAt?: number;
@@ -148,7 +147,6 @@ async function writeClawHubOriginFixture(params: {
registry,
slug: params.originSlug ?? params.slug,
...(params.ownerHandle ? { ownerHandle: params.ownerHandle } : {}),
...(params.requestedReference ? { requestedReference: params.requestedReference } : {}),
installedVersion,
installedAt,
},
@@ -170,9 +168,6 @@ async function writeClawHubOriginFixture(params: {
installedAt,
registry,
...(params.ownerHandle ? { ownerHandle: params.ownerHandle } : {}),
...(params.requestedReference
? { requestedReference: params.requestedReference }
: {}),
},
},
},
@@ -336,102 +331,6 @@ describe("skills-clawhub", () => {
});
});
it("installs skills-sh references via a ClawHub-approved pinned GitHub commit", async () => {
const commit = "a".repeat(40);
const reference = "skills-sh:openclaw/skills/weather";
fetchClawHubSkillInstallResolutionMock.mockResolvedValueOnce({
ok: true,
slug: "weather",
installKind: "github",
github: {
repo: "openclaw/skills",
path: "skills/weather",
commit,
contentHash: "sha256:approved",
sourceUrl: `https://github.com/openclaw/skills/tree/${commit}/skills/weather`,
},
});
withExtractedArchiveRootMock.mockImplementationOnce(async (params) => {
expect(params.rootMarkers).toBeUndefined();
return await params.onExtracted("/tmp/extracted-github-repo");
});
installPackageDirMock.mockResolvedValueOnce({
ok: true,
targetDir: "/tmp/workspace/skills/weather",
});
const result = await installSkillFromClawHub({
workspaceDir: "/tmp/workspace",
slug: reference,
});
expect(fetchClawHubSkillInstallResolutionMock).toHaveBeenCalledWith({
slug: "weather",
baseUrl: undefined,
requestedReference: reference,
});
expect(downloadClawHubGitHubSkillArchiveMock).toHaveBeenCalledWith({
repo: "openclaw/skills",
commit,
});
expect(installPolicyInput()).toMatchObject({
requestedSpecifier: reference,
origin: {
slug: "weather",
version: commit,
repo: "openclaw/skills",
path: "skills/weather",
commit,
},
});
expectInstalledSkill(result, {
slug: "weather",
version: commit,
targetDir: "/tmp/workspace/skills/weather",
});
expect(reportClawHubSkillInstallTelemetryMock).toHaveBeenCalledWith({
baseUrl: undefined,
slug: "weather",
version: commit,
requestedReference: reference,
});
});
it.each([
"skills-sh:",
"skills-sh:owner/repo",
"skills-sh:owner/repo/slug/extra",
"skills-sh:-owner/repo/slug",
"skills-sh:owner/../slug",
])("rejects invalid skills-sh reference %s before network access", async (reference) => {
const result = await installSkillFromClawHub({
workspaceDir: "/tmp/workspace",
slug: reference,
});
expect(result).toMatchObject({
ok: false,
error: expect.stringContaining("Invalid skills.sh skill reference"),
});
expect(fetchClawHubSkillInstallResolutionMock).not.toHaveBeenCalled();
expect(downloadClawHubGitHubSkillArchiveMock).not.toHaveBeenCalled();
});
it("rejects versions for skills-sh references before network access", async () => {
const result = await installSkillFromClawHub({
workspaceDir: "/tmp/workspace",
slug: "skills-sh:openclaw/skills/weather",
version: "1.2.3",
});
expect(result).toEqual({
ok: false,
error: "--version is not supported for skills-sh references.",
});
expect(fetchClawHubSkillInstallResolutionMock).not.toHaveBeenCalled();
expect(downloadClawHubSkillArchiveMock).not.toHaveBeenCalled();
});
it("resolves an exact skill artifact without mutating the workspace", async () => {
const integrity = `sha256-${Buffer.from("a".repeat(64), "hex").toString("base64")}`;
downloadClawHubSkillArchiveMock.mockResolvedValueOnce({
+5 -71
View File
@@ -76,7 +76,6 @@ type ClawHubSkillLockEntry = {
installedAt: number;
registry?: string;
ownerHandle?: string;
requestedReference?: string;
sourceUrl?: string;
artifact?: ClawHubSkillDownloadedArtifactLock;
skillFile?: ClawHubSkillFileLock;
@@ -89,7 +88,6 @@ type ClawHubSkillOrigin = {
registry: string;
slug: string;
ownerHandle?: string;
requestedReference?: string;
installedVersion: string;
installedAt: number;
sourceUrl?: string;
@@ -115,7 +113,6 @@ export type ClawHubSkillStatusLink =
registry: string;
slug: string;
ownerHandle?: string;
requestedReference?: string;
installedVersion: string;
installedAt: number;
originPath: string;
@@ -179,12 +176,9 @@ type Logger = {
type ClawHubSkillRef = {
slug: string;
ownerHandle?: string;
requestedReference?: string;
};
const CLAWHUB_OWNER_HANDLE_PATTERN = /^[a-z0-9](?:[a-z0-9._-]{0,38}[a-z0-9])?$/;
const GITHUB_OWNER_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/;
const GITHUB_REPO_PATTERN = /^[A-Za-z0-9._-]{1,100}$/;
function normalizeClawHubOwnerHandle(raw: string): string {
const ownerHandle = raw.trim().toLowerCase();
@@ -196,28 +190,6 @@ function normalizeClawHubOwnerHandle(raw: string): string {
function parseRequestedClawHubSkillRef(raw: string): ClawHubSkillRef {
const value = raw.trim();
if (value.startsWith("skills-sh:")) {
const parts = value.slice("skills-sh:".length).split("/");
if (parts.length !== 3) {
throw new Error(`Invalid skills.sh skill reference: ${raw}`);
}
const [owner, repo, slug] = parts;
if (
!owner ||
!repo ||
!slug ||
!GITHUB_OWNER_PATTERN.test(owner) ||
!GITHUB_REPO_PATTERN.test(repo) ||
repo === "." ||
repo === ".."
) {
throw new Error(`Invalid skills.sh skill reference: ${raw}`);
}
return {
slug: validateRequestedSkillSlug(slug),
requestedReference: value,
};
}
if (!value.startsWith("@")) {
return { slug: validateRequestedSkillSlug(value) };
}
@@ -245,10 +217,9 @@ async function resolveRequestedUpdateSlug(params: {
lock: ClawHubSkillsLockfile;
}): Promise<string> {
const requested = params.requestedSlug.trim();
const requestedRef =
requested.startsWith("@") || requested.startsWith("skills-sh:")
? parseRequestedClawHubSkillRef(requested)
: { slug: normalizeTrackedSkillSlug(requested) };
const requestedRef = requested.startsWith("@")
? parseRequestedClawHubSkillRef(requested)
: { slug: normalizeTrackedSkillSlug(requested) };
const trackedSlug = requestedRef.slug;
const trackedTargetDir = resolveWorkspaceSkillInstallDir(params.workspaceDir, trackedSlug);
const trackedOrigin = await readClawHubSkillOrigin(trackedTargetDir);
@@ -261,16 +232,6 @@ async function resolveRequestedUpdateSlug(params: {
`Skill "${trackedSlug}" is tracked as ${trackedRef}, not @${requestedRef.ownerHandle}/${trackedSlug}.`,
);
}
const trackedRequestedReference =
trackedOrigin?.requestedReference ?? trackedLockEntry?.requestedReference;
if (
requestedRef.requestedReference &&
trackedRequestedReference !== requestedRef.requestedReference
) {
throw new Error(
`Skill "${trackedSlug}" is not tracked from ${requestedRef.requestedReference}.`,
);
}
return trackedSlug;
}
return validateRequestedSkillSlug(requestedRef.slug);
@@ -280,7 +241,6 @@ type ClawHubInstallParams = {
workspaceDir: string;
slug: string;
ownerHandle?: string;
requestedReference?: string;
version?: string;
expectedIntegrity?: string;
baseUrl?: string;
@@ -377,7 +337,6 @@ type TrackedUpdateTarget =
ok: true;
slug: string;
ownerHandle?: string;
requestedReference?: string;
baseUrl?: string;
previousVersion: string | null;
}
@@ -395,7 +354,6 @@ type ClawHubSkillVerificationTargetResult =
ok: true;
slug: string;
ownerHandle?: string;
requestedReference?: string;
baseUrl: string;
version: string | undefined;
tag: string | undefined;
@@ -940,13 +898,11 @@ export function resolveClawHubSkillStatusLinkSync(params: {
locked.registry === undefined ? originRegistry : normalizeStoredRegistry(locked.registry);
const lockedSourceUrl = normalizeOptionalStringValue(locked.sourceUrl);
const lockedOwnerHandle = normalizeOptionalStringValue(locked.ownerHandle);
const lockedRequestedReference = normalizeOptionalStringValue(locked.requestedReference);
const lockedArtifact = normalizeDownloadedArtifactLock(locked.artifact);
const lockedSkillFile = normalizeSkillFileLock(locked.skillFile);
const lockedFileTreeSha256 = normalizeOptionalStringValue(locked.fileTreeSha256);
const provenanceMatches =
originRead.origin.ownerHandle === lockedOwnerHandle &&
originRead.origin.requestedReference === lockedRequestedReference &&
originRead.origin.sourceUrl === lockedSourceUrl &&
originRead.origin.artifact?.kind === lockedArtifact?.kind &&
originRead.origin.artifact?.sha256 === lockedArtifact?.sha256 &&
@@ -980,7 +936,6 @@ export function resolveClawHubSkillStatusLinkSync(params: {
registry: lockedRegistry,
slug: trackedSlug,
...(lockedOwnerHandle ? { ownerHandle: lockedOwnerHandle } : {}),
...(lockedRequestedReference ? { requestedReference: lockedRequestedReference } : {}),
installedVersion: locked.version,
installedAt: locked.installedAt,
originPath: originRead.path,
@@ -1127,13 +1082,11 @@ export async function resolveClawHubSkillVerificationTarget(params: {
const lockedRegistry =
locked.registry === undefined ? originRegistry : normalizeStoredRegistry(locked.registry);
const lockedOwnerHandle = normalizeOptionalStringValue(locked.ownerHandle);
const lockedRequestedReference = normalizeOptionalStringValue(locked.requestedReference);
if (
locked.version !== originRead.origin.installedVersion ||
locked.installedAt !== originRead.origin.installedAt ||
lockedRegistry !== originRegistry ||
originRead.origin.ownerHandle !== lockedOwnerHandle ||
originRead.origin.requestedReference !== lockedRequestedReference
originRead.origin.ownerHandle !== lockedOwnerHandle
) {
return {
ok: false,
@@ -1156,7 +1109,6 @@ export async function resolveClawHubSkillVerificationTarget(params: {
ok: true,
slug: trackedSlug,
...(lockedOwnerHandle ? { ownerHandle: lockedOwnerHandle } : {}),
...(lockedRequestedReference ? { requestedReference: lockedRequestedReference } : {}),
baseUrl: lockedRegistry,
version: version ?? (tag ? undefined : locked.version),
tag,
@@ -1190,9 +1142,6 @@ export async function resolveClawHubSkillVerificationTarget(params: {
ok: true,
slug: requestedRef.slug,
...(requestedRef.ownerHandle ? { ownerHandle: requestedRef.ownerHandle } : {}),
...(requestedRef.requestedReference
? { requestedReference: requestedRef.requestedReference }
: {}),
baseUrl: registry,
version,
tag,
@@ -1303,7 +1252,6 @@ async function installGitHubResolution(params: {
authority: "official" | "third-party";
repo: string;
commit: string;
requestedReference?: string;
force?: boolean;
logger?: Logger;
config?: OpenClawConfig;
@@ -1338,9 +1286,7 @@ async function installGitHubResolution(params: {
mutable: false,
network: true,
},
requestedSpecifier:
params.requestedReference ??
`clawhub:${formatClawHubSkillRef(params)}@${params.commit}`,
requestedSpecifier: `clawhub:${formatClawHubSkillRef(params)}@${params.commit}`,
},
rootMarkers: CLAWHUB_SKILL_ARCHIVE_ROOT_MARKERS,
}),
@@ -1463,7 +1409,6 @@ async function performClawHubSkillInstall(
await fetchClawHubSkillInstallResolution({
slug: params.slug,
...(params.ownerHandle ? { ownerHandle: params.ownerHandle } : {}),
...(params.requestedReference ? { requestedReference: params.requestedReference } : {}),
baseUrl: params.baseUrl,
...(params.forceInstall ? { forceInstall: true } : {}),
}),
@@ -1534,7 +1479,6 @@ async function performClawHubSkillInstall(
authority: officialClawHubSkill ? "official" : "third-party",
repo: latestResolution.github.repo,
commit: latestResolution.github.commit,
requestedReference: params.requestedReference,
force: params.force,
logger: params.logger,
config: params.config,
@@ -1592,7 +1536,6 @@ async function performClawHubSkillInstall(
registry: resolveClawHubBaseUrl(params.baseUrl),
slug: params.slug,
...(params.ownerHandle ? { ownerHandle: params.ownerHandle } : {}),
...(params.requestedReference ? { requestedReference: params.requestedReference } : {}),
installedVersion: version,
installedAt,
...(sourceUrl ? { sourceUrl } : {}),
@@ -1606,7 +1549,6 @@ async function performClawHubSkillInstall(
installedAt,
registry: resolveClawHubBaseUrl(params.baseUrl),
...(params.ownerHandle ? { ownerHandle: params.ownerHandle } : {}),
...(params.requestedReference ? { requestedReference: params.requestedReference } : {}),
...(sourceUrl ? { sourceUrl } : {}),
artifact,
...(skillFile ? { skillFile } : {}),
@@ -1628,7 +1570,6 @@ async function performClawHubSkillInstall(
slug: params.slug,
...(params.ownerHandle ? { ownerHandle: params.ownerHandle } : {}),
version,
...(params.requestedReference ? { requestedReference: params.requestedReference } : {}),
}).catch(() => undefined);
return {
@@ -1655,14 +1596,10 @@ async function installRequestedSkillFromClawHub(
): Promise<InstallClawHubSkillResult> {
try {
const ref = parseRequestedClawHubSkillRef(params.slug);
if (ref.requestedReference && params.version) {
throw new Error("--version is not supported for skills-sh references.");
}
return await performClawHubSkillInstall({
...params,
slug: ref.slug,
...(ref.ownerHandle ? { ownerHandle: ref.ownerHandle } : {}),
...(ref.requestedReference ? { requestedReference: ref.requestedReference } : {}),
});
} catch (err) {
return {
@@ -1831,12 +1768,10 @@ async function resolveTrackedUpdateTarget(params: {
}
const lockEntry = params.lock.skills[params.slug];
const ownerHandle = origin?.ownerHandle ?? lockEntry?.ownerHandle;
const requestedReference = origin?.requestedReference ?? lockEntry?.requestedReference;
return {
ok: true,
slug: params.slug,
...(ownerHandle ? { ownerHandle } : {}),
...(requestedReference ? { requestedReference } : {}),
baseUrl: origin?.registry ?? params.baseUrl,
previousVersion: origin?.installedVersion ?? lockEntry?.version ?? null,
};
@@ -1918,7 +1853,6 @@ export async function updateSkillsFromClawHub(params: {
workspaceDir: params.workspaceDir,
slug: tracked.slug,
...(tracked.ownerHandle ? { ownerHandle: tracked.ownerHandle } : {}),
...(tracked.requestedReference ? { requestedReference: tracked.requestedReference } : {}),
baseUrl: tracked.baseUrl,
force: true,
forceInstall: params.forceInstall,