@duyquangnvx/agent-cli 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/dist/agent-cli.js +16 -12
- package/dist/agent-cli.js.map +1 -1
- package/dist/built-ins/commands.d.ts +2 -2
- package/dist/built-ins/commands.js +2 -2
- package/dist/built-ins/doctor.js +0 -2
- package/dist/built-ins/doctor.js.map +1 -1
- package/dist/built-ins/install/dependency.js +2 -0
- package/dist/built-ins/install/dependency.js.map +1 -1
- package/dist/built-ins/install/global-npm.d.ts +2 -0
- package/dist/built-ins/install/global-npm.js +7 -3
- package/dist/built-ins/install/global-npm.js.map +1 -1
- package/dist/built-ins/install/global.d.ts +1 -1
- package/dist/built-ins/install/global.js +11 -7
- package/dist/built-ins/install/global.js.map +1 -1
- package/dist/built-ins/install/install.d.ts +5 -0
- package/dist/built-ins/install/install.js +2 -0
- package/dist/built-ins/install/install.js.map +1 -1
- package/dist/built-ins/install/release-check.d.ts +8 -0
- package/dist/built-ins/install/release-check.js +133 -0
- package/dist/built-ins/install/release-check.js.map +1 -0
- package/dist/built-ins/npm.d.ts +13 -3
- package/dist/built-ins/npm.js +13 -6
- package/dist/built-ins/npm.js.map +1 -1
- package/dist/built-ins/setup.d.ts +6 -0
- package/dist/built-ins/setup.js +168 -0
- package/dist/built-ins/setup.js.map +1 -0
- package/dist/built-ins/skill/home.d.ts +28 -0
- package/dist/built-ins/skill/home.js +116 -0
- package/dist/built-ins/skill/home.js.map +1 -0
- package/dist/built-ins/skill/install-command.d.ts +0 -13
- package/dist/built-ins/skill/install-command.js +7 -58
- package/dist/built-ins/skill/install-command.js.map +1 -1
- package/dist/built-ins/skill/project.d.ts +5 -0
- package/dist/built-ins/skill/project.js +46 -0
- package/dist/built-ins/skill/project.js.map +1 -0
- package/dist/built-ins/skill/skill.d.ts +7 -31
- package/dist/built-ins/skill/skill.js +18 -6
- package/dist/built-ins/skill/skill.js.map +1 -1
- package/dist/built-ins/skill/sync.d.ts +16 -0
- package/dist/built-ins/skill/sync.js +35 -0
- package/dist/built-ins/skill/sync.js.map +1 -0
- package/dist/built-ins/update.d.ts +2 -2
- package/dist/built-ins/update.js +23 -20
- package/dist/built-ins/update.js.map +1 -1
- package/dist/built-ins/upgrades.d.ts +1 -0
- package/dist/built-ins/upgrades.js +5 -0
- package/dist/built-ins/upgrades.js.map +1 -1
- package/dist/context/tools.d.ts +1 -0
- package/dist/context/tools.js +1 -1
- package/dist/context/tools.js.map +1 -1
- package/dist/define.d.ts +28 -34
- package/dist/define.js.map +1 -1
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +5 -1
- package/dist/errors.js.map +1 -1
- package/dist/exit-classes.js +1 -0
- package/dist/exit-classes.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/output.js +5 -3
- package/dist/output.js.map +1 -1
- package/dist/run-cli.js +2 -6
- package/dist/run-cli.js.map +1 -1
- package/dist/run-command.js +6 -8
- package/dist/run-command.js.map +1 -1
- package/dist/runtime-codes.d.ts +1 -0
- package/dist/runtime-codes.js +2 -0
- package/dist/runtime-codes.js.map +1 -1
- package/docs/README.md +1 -1
- package/docs/getting-started.md +6 -6
- package/docs/guides/doctor.md +3 -4
- package/docs/guides/errors.md +2 -0
- package/docs/guides/shipping.md +35 -23
- package/docs/principles.md +1 -1
- package/docs/reference.md +1 -0
- package/package.json +1 -1
- package/dist/built-ins/skill/hub.d.ts +0 -8
- package/dist/built-ins/skill/hub.js +0 -114
- package/dist/built-ins/skill/hub.js.map +0 -1
- package/dist/built-ins/skill/packaged.d.ts +0 -13
- package/dist/built-ins/skill/packaged.js +0 -97
- package/dist/built-ins/skill/packaged.js.map +0 -1
- package/dist/built-ins/skill/usage-hint.d.ts +0 -4
- package/dist/built-ins/skill/usage-hint.js +0 -28
- package/dist/built-ins/skill/usage-hint.js.map +0 -1
package/dist/built-ins/npm.js
CHANGED
|
@@ -48,8 +48,12 @@ export function scopeOf(name) {
|
|
|
48
48
|
export function installCommandLine(registry, version = "latest") {
|
|
49
49
|
return ["npm", "install", "--global", `${registry.package}@${version}`, ...registry.flags].join(" ");
|
|
50
50
|
}
|
|
51
|
+
/** The line that sets a Global install up, run before the CLI is on the machine. */
|
|
52
|
+
export function setupCommandLine({ package: name, flags }) {
|
|
53
|
+
return ["npx", "-y", ...flags, `${name}@latest`, "setup"].join(" ");
|
|
54
|
+
}
|
|
51
55
|
// Under nvm the first npm on PATH may belong to another Node, and install there.
|
|
52
|
-
function npmOf(ctx, windows) {
|
|
56
|
+
export function npmOf(ctx, windows) {
|
|
53
57
|
const beside = ctx.node === undefined ? undefined : join(dirname(ctx.node), windows ? "npm.cmd" : "npm");
|
|
54
58
|
if (beside === undefined || !existsSync(beside))
|
|
55
59
|
return { path: "npm", env: ctx.env };
|
|
@@ -89,7 +93,7 @@ function failureOf(call, answer, ctx) {
|
|
|
89
93
|
const output = tail(answer.stderr);
|
|
90
94
|
const next = [ctx.rerun];
|
|
91
95
|
if (code !== undefined && NETWORK_CODES.has(code)) {
|
|
92
|
-
return
|
|
96
|
+
return runtimeError({
|
|
93
97
|
code: REGISTRY_UNREACHABLE,
|
|
94
98
|
message: `npm could not reach ${registry} (${code})${output}`,
|
|
95
99
|
hint: `${unreachableHint}, then ${RUN_AGAIN}`,
|
|
@@ -97,7 +101,7 @@ function failureOf(call, answer, ctx) {
|
|
|
97
101
|
});
|
|
98
102
|
}
|
|
99
103
|
if (code !== undefined && AUTH_CODES.has(code)) {
|
|
100
|
-
return
|
|
104
|
+
return runtimeError({
|
|
101
105
|
code: REGISTRY_AUTH,
|
|
102
106
|
message: `${registry} refused npm's credentials (${code})${output}`,
|
|
103
107
|
hint: authHint(code, ctx),
|
|
@@ -115,7 +119,7 @@ function failureOf(call, answer, ctx) {
|
|
|
115
119
|
next: [...next, wholeLine(installCommandLine(ctx.registry))],
|
|
116
120
|
});
|
|
117
121
|
}
|
|
118
|
-
return
|
|
122
|
+
return runtimeError({
|
|
119
123
|
code: NPM_FAILED,
|
|
120
124
|
message: `npm ${call} failed with exit code ${answer.exitCode}${output}`,
|
|
121
125
|
hint: `fix what npm reports, then ${RUN_AGAIN}`,
|
|
@@ -180,9 +184,12 @@ export async function installGlobally(version, ctx) {
|
|
|
180
184
|
...ctx.registry.flags,
|
|
181
185
|
], ctx, null);
|
|
182
186
|
}
|
|
187
|
+
export function latestViewArgs({ package: name, flags }) {
|
|
188
|
+
return ["view", `${name}@latest`, "version", "--json", ...flags];
|
|
189
|
+
}
|
|
183
190
|
export async function latestVersion(ctx) {
|
|
184
|
-
const { package: name, label: registry
|
|
185
|
-
const answer = await runNpm("view",
|
|
191
|
+
const { package: name, label: registry } = ctx.registry;
|
|
192
|
+
const answer = await runNpm("view", latestViewArgs(ctx.registry), ctx);
|
|
186
193
|
const version = versionInViewAnswer(answer);
|
|
187
194
|
if (version === undefined) {
|
|
188
195
|
throw noLatest(ctx, `npm answered no version for ${name}@latest on ${registry}: ${answer.trim()}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"npm.js","sourceRoot":"","sources":["../../src/built-ins/npm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAoB,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGnE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,
|
|
1
|
+
{"version":3,"file":"npm.js","sourceRoot":"","sources":["../../src/built-ins/npm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Command, GlobalInstall } from "../define.js";
|
|
2
|
+
import type { Launch } from "./commands.js";
|
|
3
|
+
import type { SkillCli } from "./skill/skill.js";
|
|
4
|
+
export declare const NOT_ON_PATH = "NOT_ON_PATH";
|
|
5
|
+
/** The built-in `setup`, which runs from any copy, such as npx's, so it never asks to be the global one. */
|
|
6
|
+
export declare function setupCommand(cli: SkillCli, install: GlobalInstall, { node }: Launch): Command;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { lstat, readFile, realpath } from "node:fs/promises";
|
|
2
|
+
import { delimiter, join, normalize } from "node:path";
|
|
3
|
+
import * as z from "zod";
|
|
4
|
+
import { DISK_FULL, PERMISSION_DENIED } from "../context/errno.js";
|
|
5
|
+
import { INTERRUPTED } from "../context/interrupts.js";
|
|
6
|
+
import { pathOf } from "../context/tools.js";
|
|
7
|
+
import { defineCommand } from "../define-command.js";
|
|
8
|
+
import { CliError, orMissing, runtimeError } from "../errors.js";
|
|
9
|
+
import { wholeLine } from "../next-step.js";
|
|
10
|
+
import { globalModulesDir, globalNpm, NOT_GLOBAL_INSTALL, setupLineOf, } from "./install/global-npm.js";
|
|
11
|
+
import { globalPrefix, INSTALL_FAILED, installGlobally, latestVersion, } from "./npm.js";
|
|
12
|
+
import { standingOf } from "./semver.js";
|
|
13
|
+
import { homeCopiesOf, homeSyncSchema, renderHomeSync, renderPlannedSync, syncHome, } from "./skill/home.js";
|
|
14
|
+
import { renderUpgrade, upgradeSchema, upgradesOf } from "./upgrades.js";
|
|
15
|
+
export const NOT_ON_PATH = "NOT_ON_PATH";
|
|
16
|
+
const setupSchema = z.object({
|
|
17
|
+
version: z.string(),
|
|
18
|
+
prefix: z.string(),
|
|
19
|
+
installed: z.boolean(),
|
|
20
|
+
skill: homeSyncSchema.nullable(),
|
|
21
|
+
upgrades: z.array(upgradeSchema),
|
|
22
|
+
docs: z.string().nullable(),
|
|
23
|
+
});
|
|
24
|
+
const installedManifest = z.object({ version: z.string() });
|
|
25
|
+
async function versionAt(packageDir) {
|
|
26
|
+
const text = await orMissing(readFile(join(packageDir, "package.json"), "utf8"));
|
|
27
|
+
if (text === undefined)
|
|
28
|
+
return null;
|
|
29
|
+
try {
|
|
30
|
+
const parsed = installedManifest.safeParse(JSON.parse(text));
|
|
31
|
+
return parsed.success ? parsed.data.version : null;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
// A manifest npm left unreadable is a broken install, which the install below replaces.
|
|
35
|
+
if (error instanceof SyntaxError)
|
|
36
|
+
return null;
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// The Run-as would not run yet, so every Next step is the line that started this.
|
|
41
|
+
function npmOfSetup(cli, install, ctx, node) {
|
|
42
|
+
return { ...globalNpm(cli, install, ctx, node), rerun: wholeLine(setupLineOf(install)) };
|
|
43
|
+
}
|
|
44
|
+
function needsInstall({ from, latest }) {
|
|
45
|
+
return from === null || standingOf(from, latest) === "behind";
|
|
46
|
+
}
|
|
47
|
+
function binDirOf(prefix) {
|
|
48
|
+
return process.platform === "win32" ? prefix : join(prefix, "bin");
|
|
49
|
+
}
|
|
50
|
+
// A PATH entry that cannot be resolved still compares as written, so it only fails to match.
|
|
51
|
+
async function canonical(path) {
|
|
52
|
+
return normalize(await realpath(path).catch(() => path));
|
|
53
|
+
}
|
|
54
|
+
// npx puts its own copy's bin on PATH, so only the global folder's place there tells a later shell finds it.
|
|
55
|
+
async function assertOnPath(cli, prefix, node, ctx) {
|
|
56
|
+
const binDir = binDirOf(prefix);
|
|
57
|
+
const wanted = await canonical(binDir);
|
|
58
|
+
const entries = pathOf(ctx.env).split(delimiter).filter(Boolean);
|
|
59
|
+
const found = await Promise.all(entries.map(canonical));
|
|
60
|
+
if (found.includes(wanted))
|
|
61
|
+
return;
|
|
62
|
+
throw runtimeError({
|
|
63
|
+
code: NOT_ON_PATH,
|
|
64
|
+
message: `${cli.name} is installed in ${binDir}, by the npm of ${node ?? "the Node on PATH"}, a folder not on this shell's PATH`,
|
|
65
|
+
hint: `add ${binDir} to PATH, or ask your user which Node their terminal runs and run this under it`,
|
|
66
|
+
next: [],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const REFUSED = new Set([PERMISSION_DENIED, DISK_FULL, INSTALL_FAILED]);
|
|
70
|
+
// These name the Run-as or a bare npm install, neither of which finishes the job from npx's copy.
|
|
71
|
+
function withSetupLine(error, install) {
|
|
72
|
+
if (!(error instanceof CliError) || !REFUSED.has(error.code))
|
|
73
|
+
return error;
|
|
74
|
+
return runtimeError({
|
|
75
|
+
code: error.code,
|
|
76
|
+
message: error.message,
|
|
77
|
+
hint: error.code === INSTALL_FAILED
|
|
78
|
+
? "fix what npm reports, then run the Next step; if a sandbox refused it, ask your user to type ! then that line"
|
|
79
|
+
: error.hint,
|
|
80
|
+
next: [wholeLine(setupLineOf(install))],
|
|
81
|
+
}, { cause: error });
|
|
82
|
+
}
|
|
83
|
+
function renderSetup(cli, install, setup) {
|
|
84
|
+
const { version, prefix, docs } = setup;
|
|
85
|
+
return [
|
|
86
|
+
setup.installed
|
|
87
|
+
? `installed ${install.package}@${version} with the npm under ${prefix}`
|
|
88
|
+
: `${install.package}@${version} is already installed under ${prefix}`,
|
|
89
|
+
...renderHomeSync(cli.name, setup.skill),
|
|
90
|
+
...setup.upgrades.map(renderUpgrade),
|
|
91
|
+
...(docs === null ? [] : [`docs ${docs}`, `Read that folder before using ${cli.name}.`]),
|
|
92
|
+
].join("\n");
|
|
93
|
+
}
|
|
94
|
+
/** The built-in `setup`, which runs from any copy, such as npx's, so it never asks to be the global one. */
|
|
95
|
+
export function setupCommand(cli, install, { node }) {
|
|
96
|
+
return defineCommand({
|
|
97
|
+
description: "install this CLI and its skill on this machine",
|
|
98
|
+
examples: [
|
|
99
|
+
{ command: `${cli.name} setup`, note: "install the latest version and the skill" },
|
|
100
|
+
{ command: `${cli.name} setup --dry-run`, note: "show what it would change" },
|
|
101
|
+
],
|
|
102
|
+
effect: "write",
|
|
103
|
+
output: setupSchema,
|
|
104
|
+
plan: async (_input, ctx) => {
|
|
105
|
+
const npm = npmOfSetup(cli, install, ctx, node);
|
|
106
|
+
const prefix = await globalPrefix(npm);
|
|
107
|
+
const packageDir = join(globalModulesDir(prefix), install.package);
|
|
108
|
+
// `npm link` puts a symlink to a source checkout where the install would be.
|
|
109
|
+
if ((await orMissing(lstat(packageDir)))?.isSymbolicLink() === true) {
|
|
110
|
+
throw runtimeError({
|
|
111
|
+
code: NOT_GLOBAL_INSTALL,
|
|
112
|
+
message: `${packageDir} is a link (npm link), which an install would replace`,
|
|
113
|
+
hint: "remove the link with npm unlink, then run the Next step",
|
|
114
|
+
next: [wholeLine(setupLineOf(install))],
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
package: install.package,
|
|
119
|
+
from: await versionAt(packageDir),
|
|
120
|
+
latest: await latestVersion(npm),
|
|
121
|
+
prefix,
|
|
122
|
+
packageDir,
|
|
123
|
+
copies: cli.skill === undefined ? [] : await homeCopiesOf(cli.name, ctx.env),
|
|
124
|
+
};
|
|
125
|
+
},
|
|
126
|
+
apply: async (plan, ctx) => {
|
|
127
|
+
const { from, latest, prefix, packageDir } = plan;
|
|
128
|
+
const installs = needsInstall(plan);
|
|
129
|
+
const skill = await ctx
|
|
130
|
+
.runToEnd(`installing ${plan.package}@${latest}`, async () => {
|
|
131
|
+
if (installs) {
|
|
132
|
+
ctx.progress(`installing ${plan.package}@${latest} with the npm under ${prefix}…`);
|
|
133
|
+
await installGlobally(latest, npmOfSetup(cli, install, ctx, node));
|
|
134
|
+
}
|
|
135
|
+
return syncHome(cli, packageDir, ctx);
|
|
136
|
+
})
|
|
137
|
+
.catch((error) => {
|
|
138
|
+
throw withSetupLine(error, install);
|
|
139
|
+
});
|
|
140
|
+
const setup = {
|
|
141
|
+
version: installs || from === null ? latest : from,
|
|
142
|
+
prefix,
|
|
143
|
+
installed: installs,
|
|
144
|
+
skill,
|
|
145
|
+
upgrades: installs && from !== null ? await upgradesOf(packageDir, from, latest) : [],
|
|
146
|
+
docs: cli.docs === undefined ? null : join(packageDir, cli.docs),
|
|
147
|
+
};
|
|
148
|
+
ctx.deliver(setup);
|
|
149
|
+
if (ctx.signal.aborted) {
|
|
150
|
+
throw new CliError({
|
|
151
|
+
code: INTERRUPTED,
|
|
152
|
+
message: `interrupted, but ${plan.package}@${setup.version} and its skill are already in place`,
|
|
153
|
+
hint: "nothing to run again",
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
await assertOnPath(cli, prefix, node, ctx);
|
|
157
|
+
return setup;
|
|
158
|
+
},
|
|
159
|
+
render: (setup) => renderSetup(cli, install, setup),
|
|
160
|
+
renderPlan: (plan) => [
|
|
161
|
+
needsInstall(plan)
|
|
162
|
+
? `would install ${plan.package}@${plan.latest} with the npm under ${plan.prefix}`
|
|
163
|
+
: `${plan.package}@${plan.from} is already installed under ${plan.prefix}`,
|
|
164
|
+
...renderPlannedSync(cli.name, plan.copies),
|
|
165
|
+
].join("\n"),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/built-ins/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import type { Context, Env } from "../../context.js";
|
|
3
|
+
import type { SkillSource } from "../../define.js";
|
|
4
|
+
import type { Install } from "../install/install.js";
|
|
5
|
+
import type { Skill, SkillCli } from "./skill.js";
|
|
6
|
+
/** The version a SKILL.md's frontmatter `metadata.version` states. */
|
|
7
|
+
export declare function skillVersionIn(skill: string): string | undefined;
|
|
8
|
+
/** How the row words a copy that states a version, which only a skill from before CLI docs does. */
|
|
9
|
+
export declare function statedVersionNote(version: string): string;
|
|
10
|
+
export declare function homeOf(env: Env): string;
|
|
11
|
+
/** The home folders of the Skill copy; the skills installer may have made one a link to the other. */
|
|
12
|
+
export declare function homeCopiesOf(name: string, env: Env): Promise<string[]>;
|
|
13
|
+
export declare const homeSyncSchema: z.ZodObject<{
|
|
14
|
+
copies: z.ZodArray<z.ZodString>;
|
|
15
|
+
written: z.ZodArray<z.ZodString>;
|
|
16
|
+
removed: z.ZodArray<z.ZodString>;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
export type HomeSync = z.infer<typeof homeSyncSchema>;
|
|
19
|
+
/**
|
|
20
|
+
* Makes each home Skill copy match the folder in the package at `packageDir`. Null when the CLI
|
|
21
|
+
* declares no skill, or that package ships none, which must not empty a copy.
|
|
22
|
+
*/
|
|
23
|
+
export declare function syncHome(cli: Pick<SkillCli, "name" | "skill">, packageDir: string, ctx: Context): Promise<HomeSync | null>;
|
|
24
|
+
/** What a dry run says of the copies, since the release's files may not be on disk yet. */
|
|
25
|
+
export declare function renderPlannedSync(name: string, copies: readonly string[]): readonly string[];
|
|
26
|
+
export declare function renderHomeSync(name: string, sync: HomeSync | null): readonly string[];
|
|
27
|
+
/** A skill the package ships, which `setup` and `update` copy under home. */
|
|
28
|
+
export declare function homeSkill(cli: SkillCli, { folder }: SkillSource, install: Install): Skill;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { readFile, realpath } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import * as z from "zod";
|
|
5
|
+
import { isMissingFile, orMissing } from "../../errors.js";
|
|
6
|
+
import { applySync, filesIn, syncOf } from "./sync.js";
|
|
7
|
+
// The folders of Claude Code and Codex (ADR 0016).
|
|
8
|
+
const SKILL_DIRS = [
|
|
9
|
+
[".claude", "skills"],
|
|
10
|
+
[".agents", "skills"],
|
|
11
|
+
];
|
|
12
|
+
const FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
13
|
+
const METADATA_VERSION = /^metadata:[ \t]*\r?\n(?:[ \t]+.*\r?\n)*?[ \t]+version:[ \t]*["']?([^"'\s]+)["']?[ \t]*$/m;
|
|
14
|
+
/** The version a SKILL.md's frontmatter `metadata.version` states. */
|
|
15
|
+
export function skillVersionIn(skill) {
|
|
16
|
+
const frontmatter = FRONTMATTER.exec(skill)?.[1];
|
|
17
|
+
return frontmatter === undefined ? undefined : METADATA_VERSION.exec(`${frontmatter}\n`)?.[1];
|
|
18
|
+
}
|
|
19
|
+
/** How the row words a copy that states a version, which only a skill from before CLI docs does. */
|
|
20
|
+
export function statedVersionNote(version) {
|
|
21
|
+
return `states metadata.version ${version}: an older skill that CLI docs replace`;
|
|
22
|
+
}
|
|
23
|
+
export function homeOf(env) {
|
|
24
|
+
return env.HOME ?? env.USERPROFILE ?? homedir();
|
|
25
|
+
}
|
|
26
|
+
/** The home folders of the Skill copy; the skills installer may have made one a link to the other. */
|
|
27
|
+
export async function homeCopiesOf(name, env) {
|
|
28
|
+
const paths = SKILL_DIRS.map((dir) => join(homeOf(env), ...dir, name));
|
|
29
|
+
const reals = await Promise.all(paths.map(async (path) => orMissing(realpath(path))));
|
|
30
|
+
return paths.filter((_path, index) => {
|
|
31
|
+
const real = reals[index];
|
|
32
|
+
return real === undefined || reals.indexOf(real) === index;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export const homeSyncSchema = z.object({
|
|
36
|
+
copies: z.array(z.string()),
|
|
37
|
+
written: z.array(z.string()),
|
|
38
|
+
removed: z.array(z.string()),
|
|
39
|
+
});
|
|
40
|
+
/**
|
|
41
|
+
* Makes each home Skill copy match the folder in the package at `packageDir`. Null when the CLI
|
|
42
|
+
* declares no skill, or that package ships none, which must not empty a copy.
|
|
43
|
+
*/
|
|
44
|
+
export async function syncHome(cli, packageDir, ctx) {
|
|
45
|
+
if (cli.skill === undefined)
|
|
46
|
+
return null;
|
|
47
|
+
const source = join(packageDir, cli.skill.folder);
|
|
48
|
+
if ((await filesIn(source)).length === 0)
|
|
49
|
+
return null;
|
|
50
|
+
const copies = await homeCopiesOf(cli.name, ctx.env);
|
|
51
|
+
const syncs = await Promise.all(copies.map((copy) => syncOf(source, copy)));
|
|
52
|
+
for (const sync of syncs)
|
|
53
|
+
await applySync(sync, ctx);
|
|
54
|
+
return {
|
|
55
|
+
copies,
|
|
56
|
+
written: syncs.flatMap((sync) => [...sync.write, ...sync.replace]),
|
|
57
|
+
removed: syncs.flatMap((sync) => sync.remove),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** What a dry run says of the copies, since the release's files may not be on disk yet. */
|
|
61
|
+
export function renderPlannedSync(name, copies) {
|
|
62
|
+
return copies.length === 0
|
|
63
|
+
? []
|
|
64
|
+
: [`would make the ${name} skill at ${copies.join(", ")} match the release`];
|
|
65
|
+
}
|
|
66
|
+
export function renderHomeSync(name, sync) {
|
|
67
|
+
if (sync === null)
|
|
68
|
+
return [];
|
|
69
|
+
const at = sync.copies.join(", ");
|
|
70
|
+
return sync.written.length + sync.removed.length === 0
|
|
71
|
+
? [`the ${name} skill at ${at} already matches the package`]
|
|
72
|
+
: [
|
|
73
|
+
`copied the ${name} skill to ${at}: wrote ${sync.written.length} files, removed ${sync.removed.length}`,
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
async function homeCopyAt(path) {
|
|
77
|
+
try {
|
|
78
|
+
return {
|
|
79
|
+
path,
|
|
80
|
+
state: "readable",
|
|
81
|
+
stated: skillVersionIn(await readFile(join(path, "SKILL.md"), "utf8")),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
return { path, state: isMissingFile(error) ? "missing" : "unreadable" };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function describeCopy(copy) {
|
|
89
|
+
if (copy.state === "missing")
|
|
90
|
+
return `no copy at ${copy.path}`;
|
|
91
|
+
if (copy.state !== "readable")
|
|
92
|
+
return `${copy.path} (could not be read)`;
|
|
93
|
+
return copy.stated === undefined ? copy.path : `${copy.path} (${statedVersionNote(copy.stated)})`;
|
|
94
|
+
}
|
|
95
|
+
async function findingOf(cli, folder, install, ctx) {
|
|
96
|
+
const paths = await homeCopiesOf(cli.name, ctx.env);
|
|
97
|
+
const [copies, shipped] = await Promise.all([
|
|
98
|
+
Promise.all(paths.map(homeCopyAt)),
|
|
99
|
+
orMissing(readFile(join(ctx.packageRoot, folder, "SKILL.md"), "utf8")),
|
|
100
|
+
]);
|
|
101
|
+
const message = copies.map(describeCopy).join("; ");
|
|
102
|
+
// A package whose own skill states a version would rewrite it, so a fix would never clear the row.
|
|
103
|
+
const shipsStated = shipped !== undefined && skillVersionIn(shipped) !== undefined;
|
|
104
|
+
const healthy = copies.every((copy) => copy.state === "readable" && (copy.stated === undefined || shipsStated));
|
|
105
|
+
return healthy
|
|
106
|
+
? { state: "ok", message }
|
|
107
|
+
: { state: "problem", message, fix: `${install.runAs} setup` };
|
|
108
|
+
}
|
|
109
|
+
/** A skill the package ships, which `setup` and `update` copy under home. */
|
|
110
|
+
export function homeSkill(cli, { folder }, install) {
|
|
111
|
+
return {
|
|
112
|
+
builtIns: {},
|
|
113
|
+
rows: [{ name: "skill", advisory: true, run: (ctx) => findingOf(cli, folder, install, ctx) }],
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=home.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"home.js","sourceRoot":"","sources":["../../../src/built-ins/skill/home.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,18 +6,5 @@ export declare function skillCopyOf(cli: Pick<SkillCli, "name">, cwd: string): P
|
|
|
6
6
|
readonly root: string;
|
|
7
7
|
readonly copy: string;
|
|
8
8
|
}>;
|
|
9
|
-
/** The `metadata.version` each SKILL.md states, null for none; `copyVersion` is undefined with no copy. */
|
|
10
|
-
interface SkillVersions {
|
|
11
|
-
readonly packageVersion: string | null;
|
|
12
|
-
readonly copyVersion: string | null | undefined;
|
|
13
|
-
/**
|
|
14
|
-
* The copy states the package's version, so a file of it that differs was edited by hand; a copy
|
|
15
|
-
* of another version, or none, is an older install.
|
|
16
|
-
*/
|
|
17
|
-
readonly same: boolean;
|
|
18
|
-
}
|
|
19
|
-
/** The versions of the package's skill in `source` and of its copy in `copy`. */
|
|
20
|
-
export declare function skillVersionsOf(source: string, copy: string): Promise<SkillVersions>;
|
|
21
9
|
/** The built-in `skill install`, for a CLI whose skill ships in its package. */
|
|
22
10
|
export declare function skillInstallCommand(cli: SkillCli, folder: string, agents: AgentsSection | undefined): Command;
|
|
23
|
-
export {};
|
|
@@ -1,36 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { join
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
3
|
import * as z from "zod";
|
|
4
|
-
import { FORCE_FLAG } from "../../command-line/flags.js";
|
|
5
|
-
import { OUTPUT_EXISTS } from "../../context/outputs.js";
|
|
6
4
|
import { defineCommand } from "../../define-command.js";
|
|
7
|
-
import {
|
|
5
|
+
import { orMissing } from "../../errors.js";
|
|
8
6
|
import { agentsMdAt, handEditsAt, withSection, } from "../agents-md.js";
|
|
9
7
|
import { projectRootOf } from "../project-root.js";
|
|
10
|
-
import {
|
|
8
|
+
import { applySync, syncOf } from "./sync.js";
|
|
11
9
|
/** The project root and the Skill copy under it, as `skill install` writes it. */
|
|
12
10
|
export async function skillCopyOf(cli, cwd) {
|
|
13
11
|
const root = await projectRootOf(cwd);
|
|
14
12
|
return { root, copy: join(root, ".claude", "skills", cli.name) };
|
|
15
13
|
}
|
|
16
|
-
/** Every file under `dir`, relative to it and sorted; none when `dir` is missing. */
|
|
17
|
-
async function filesIn(dir) {
|
|
18
|
-
const entries = await orMissing(readdir(dir, { recursive: true, withFileTypes: true }));
|
|
19
|
-
return (entries ?? [])
|
|
20
|
-
.filter((entry) => entry.isFile())
|
|
21
|
-
.map((entry) => relative(dir, join(entry.parentPath, entry.name)))
|
|
22
|
-
.sort();
|
|
23
|
-
}
|
|
24
|
-
/** The versions of the package's skill in `source` and of its copy in `copy`. */
|
|
25
|
-
export async function skillVersionsOf(source, copy) {
|
|
26
|
-
const [shipped, installed] = await Promise.all([
|
|
27
|
-
readFile(join(source, "SKILL.md"), "utf8"),
|
|
28
|
-
orMissing(readFile(join(copy, "SKILL.md"), "utf8")),
|
|
29
|
-
]);
|
|
30
|
-
const packageVersion = skillVersionIn(shipped) ?? null;
|
|
31
|
-
const copyVersion = installed === undefined ? undefined : (skillVersionIn(installed) ?? null);
|
|
32
|
-
return { packageVersion, copyVersion, same: copyVersion === packageVersion };
|
|
33
|
-
}
|
|
34
14
|
const installSchema = z.object({
|
|
35
15
|
copy: z.string(),
|
|
36
16
|
written: z.array(z.string()),
|
|
@@ -38,22 +18,10 @@ const installSchema = z.object({
|
|
|
38
18
|
agentsMd: z.object({ path: z.string(), changed: z.boolean() }).nullable(),
|
|
39
19
|
handEdits: z.array(z.string()),
|
|
40
20
|
});
|
|
41
|
-
async function sameContent(left, right) {
|
|
42
|
-
const [a, b] = await Promise.all([readFile(left), readFile(right)]);
|
|
43
|
-
return a.equals(b);
|
|
44
|
-
}
|
|
45
21
|
async function planOf(cli, folder, agents, cwd, packageRoot) {
|
|
46
|
-
const source = join(packageRoot, folder);
|
|
47
22
|
const { root, copy } = await skillCopyOf(cli, cwd);
|
|
48
|
-
const [shipped, present] = await Promise.all([filesIn(source), filesIn(copy)]);
|
|
49
|
-
const differs = await Promise.all(shipped.map(async (file) => present.includes(file) && !(await sameContent(join(source, file), join(copy, file)))));
|
|
50
23
|
return {
|
|
51
|
-
|
|
52
|
-
copy,
|
|
53
|
-
write: shipped.filter((file) => !present.includes(file)),
|
|
54
|
-
replace: shipped.filter((_file, index) => differs[index]),
|
|
55
|
-
remove: present.filter((file) => !shipped.includes(file)),
|
|
56
|
-
sameVersion: (await skillVersionsOf(source, copy)).same,
|
|
24
|
+
...(await syncOf(join(packageRoot, folder), copy)),
|
|
57
25
|
agentsMd: agents === undefined ? null : await agentsMdAt(agents, root),
|
|
58
26
|
handEdits: agents === undefined ? [] : await handEditsAt(root),
|
|
59
27
|
};
|
|
@@ -101,16 +69,6 @@ function renderInstalled(cli, data) {
|
|
|
101
69
|
...data.handEdits.map((edit) => `by hand: ${edit}`),
|
|
102
70
|
].join("\n");
|
|
103
71
|
}
|
|
104
|
-
// The Runtime's `outputs` refusal says "overwrite", so a removal is refused here, before any write.
|
|
105
|
-
function editedRemovals(plan, ctx) {
|
|
106
|
-
const them = plan.remove.length === 1 ? "it" : "them";
|
|
107
|
-
return new CliError({
|
|
108
|
-
code: OUTPUT_EXISTS,
|
|
109
|
-
message: `skill install would remove ${plan.remove.map((file) => join(plan.copy, file)).join(", ")}`,
|
|
110
|
-
hint: `once the user agrees to remove ${them}, run the Next step`,
|
|
111
|
-
next: [ctx.rerun({ add: [FORCE_FLAG.flag] })],
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
72
|
/** The built-in `skill install`, for a CLI whose skill ships in its package. */
|
|
115
73
|
export function skillInstallCommand(cli, folder, agents) {
|
|
116
74
|
return defineCommand({
|
|
@@ -123,19 +81,10 @@ export function skillInstallCommand(cli, folder, agents) {
|
|
|
123
81
|
],
|
|
124
82
|
effect: "write",
|
|
125
83
|
output: installSchema,
|
|
126
|
-
force: "replace or remove hand-edited files of a skill copy at the package's version",
|
|
127
84
|
plan: (_input, ctx) => planOf(cli, folder, agents, ctx.cwd, ctx.packageRoot),
|
|
128
|
-
// The copy lives in the project repo, so git keeps an edit
|
|
129
|
-
outputs: (plan) => plan.sameVersion ? [...plan.write, ...plan.replace].map((file) => join(plan.copy, file)) : [],
|
|
85
|
+
// The copy lives in the project repo, so git keeps an edit this replaces.
|
|
130
86
|
apply: async (plan, ctx) => {
|
|
131
|
-
|
|
132
|
-
throw editedRemovals(plan, ctx);
|
|
133
|
-
for (const file of [...plan.write, ...plan.replace]) {
|
|
134
|
-
await ctx.files.write(join(plan.copy, file), await readFile(join(plan.source, file)));
|
|
135
|
-
}
|
|
136
|
-
for (const file of plan.remove) {
|
|
137
|
-
await ctx.files.remove(join(plan.copy, file));
|
|
138
|
-
}
|
|
87
|
+
await applySync(plan, ctx);
|
|
139
88
|
const { agentsMd } = plan;
|
|
140
89
|
if (agentsMd !== null && agentsMd.change !== null) {
|
|
141
90
|
const existing = (await orMissing(readFile(agentsMd.path, "utf8"))) ?? "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-command.js","sourceRoot":"","sources":["../../../src/built-ins/skill/install-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"install-command.js","sourceRoot":"","sources":["../../../src/built-ins/skill/install-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SkillSource } from "../../define.js";
|
|
2
|
+
import type { Install } from "../install/install.js";
|
|
3
|
+
import type { Skill, SkillCli } from "./skill.js";
|
|
4
|
+
/** A skill the package ships in `folder`, which `skill install` copies to the project root. */
|
|
5
|
+
export declare function projectSkill(cli: SkillCli, { folder, agents: text }: SkillSource, install: Install): Skill;
|