@dadado/agent-kit-cli 5.8.0 → 5.9.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/README.md +2 -1
- package/dist/index.js +464 -188
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ NO_COLOR=1 agent-kit
|
|
|
62
62
|
# → plain text (no ANSI); also plain when stdout is not a TTY or CI=1
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
Subcommands and `agent-kit --version` are unchanged. `agent-kit run <slash>` starts those project slashes headless from `.cursor/commands/` (numbered-list HITL). `/git-prod` and `/kit-prod` stay operator-gated and are omitted from that catalog.
|
|
65
|
+
Subcommands and `agent-kit --version` are unchanged. `agent-kit run <slash>` starts those project slashes headless from `.cursor/commands/` (numbered-list HITL). `agent-kit run-plan-all` is a first-class alias of `agent-kit run run-plan-all`. Typing `/run-plan-all` in zsh is a filesystem path. `/git-prod` and `/kit-prod` stay operator-gated and are omitted from that catalog.
|
|
66
66
|
|
|
67
67
|
On an interactive TTY, long-running commands (`init`, `install`, `doctor`, `update`, `run-plan` ticks) show an in-process ANSI spinner plus a rotating Mission Kit tip. Set `AGENT_KIT_REDUCED_MOTION=1` for static text on a capable TTY. Runtime dependencies stay `@clack/prompts`, `citty`, and `kolorist` (no `ora` / `figlet` / `chalk` / `ink`). Window titles for `agent-kit dashboard` and `agent-kit dashboard-broadcast` use the workspace basename, not the CLI package folder.
|
|
68
68
|
|
|
@@ -80,6 +80,7 @@ On an interactive TTY, long-running commands (`init`, `install`, `doctor`, `upda
|
|
|
80
80
|
| `agent-kit add <id>` | Install a skill or L1 pack |
|
|
81
81
|
| `agent-kit run <slash>` | One headless session from an L0 slash file (numbered-list HITL; never git-prod) |
|
|
82
82
|
| `agent-kit run-plan` | Headless continuous plan runner (never promotes to production) |
|
|
83
|
+
| `agent-kit run-plan-all` | Headless `/run-plan-all` queue from the L0 file (same as `run run-plan-all`; never git-prod) |
|
|
83
84
|
|
|
84
85
|
Run `agent-kit --help` or `agent-kit <command> --help` for the full surface.
|
|
85
86
|
|
package/dist/index.js
CHANGED
|
@@ -273,7 +273,8 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
273
273
|
"3a88df22375f90a3a6743f50d9a01129e0373f4ca8dff03fb744c1de3c149409",
|
|
274
274
|
"481a9994ccecaa611173f9ef91a1dbe7458d89758c6a6b5e7c3bbbbf460888ce",
|
|
275
275
|
"691d91fd1e9032b6f9315f29348d4473201917da257258afd74eb954298d8d71",
|
|
276
|
-
"ab0808b7dbc333e523b87b126bb655353cde2574db30d849cc9c9037843bef8c"
|
|
276
|
+
"ab0808b7dbc333e523b87b126bb655353cde2574db30d849cc9c9037843bef8c",
|
|
277
|
+
"85514e26af694bbe38e7ddf625710a32719ddf6afc173843c9cdfbffdad8e466"
|
|
277
278
|
]);
|
|
278
279
|
|
|
279
280
|
// src/lifecycle/paths.ts
|
|
@@ -942,6 +943,9 @@ function loadPackageVersion() {
|
|
|
942
943
|
}
|
|
943
944
|
var KIT_VERSION = loadPackageVersion();
|
|
944
945
|
var KIT_PACKAGE_SPEC = "@dadado/agent-kit-cli";
|
|
946
|
+
function pinnedCliSpec(version = KIT_VERSION) {
|
|
947
|
+
return `${KIT_PACKAGE_SPEC}@${version}`;
|
|
948
|
+
}
|
|
945
949
|
|
|
946
950
|
// src/manifest/index.ts
|
|
947
951
|
import path6 from "path";
|
|
@@ -3659,21 +3663,81 @@ import { constants as constants3, access as access6, readFile as readFile10, sta
|
|
|
3659
3663
|
import { homedir as homedir2 } from "os";
|
|
3660
3664
|
import path16 from "path";
|
|
3661
3665
|
var MIN_NODE_MAJOR = 20;
|
|
3662
|
-
|
|
3666
|
+
var CLI_PACKAGE_JSON_REL = path16.join(
|
|
3667
|
+
"lib",
|
|
3668
|
+
"node_modules",
|
|
3669
|
+
"@dadado",
|
|
3670
|
+
"agent-kit-cli",
|
|
3671
|
+
"package.json"
|
|
3672
|
+
);
|
|
3673
|
+
var DIST_INDEX_RE = /(?:\$\{basedir\}|\$basedir)?[^'"\s;]*dist\/index\.js/g;
|
|
3674
|
+
function extractDistIndexFromBinScript(contents) {
|
|
3675
|
+
const found = [];
|
|
3676
|
+
DIST_INDEX_RE.lastIndex = 0;
|
|
3677
|
+
for (const match of contents.matchAll(DIST_INDEX_RE)) {
|
|
3678
|
+
const raw = match[0]?.trim();
|
|
3679
|
+
if (raw) found.push(raw.replace(/\\/g, "/"));
|
|
3680
|
+
}
|
|
3681
|
+
return found;
|
|
3682
|
+
}
|
|
3683
|
+
function expandBinDirVars(raw, binDir) {
|
|
3684
|
+
return raw.replace(/\$\{basedir\}/g, binDir).replace(/\$basedir/g, binDir);
|
|
3685
|
+
}
|
|
3686
|
+
function packageJsonFromDistIndex(distIndex) {
|
|
3687
|
+
return path16.join(path16.dirname(distIndex), "..", "package.json");
|
|
3688
|
+
}
|
|
3689
|
+
function parsePackageVersion(contents) {
|
|
3690
|
+
try {
|
|
3691
|
+
const parsed = JSON.parse(contents);
|
|
3692
|
+
return typeof parsed.version === "string" && parsed.version.length > 0 ? parsed.version : null;
|
|
3693
|
+
} catch {
|
|
3694
|
+
return null;
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3697
|
+
async function readBinVersion(binPath, options = {}) {
|
|
3698
|
+
const readFileImpl = options.readFileImpl ?? ((filePath) => readFile10(filePath, "utf8"));
|
|
3699
|
+
const binDir = path16.dirname(binPath);
|
|
3700
|
+
const candidates = [
|
|
3701
|
+
path16.join(binDir, "..", CLI_PACKAGE_JSON_REL),
|
|
3702
|
+
path16.join(binDir, "..", "node_modules", "@dadado", "agent-kit-cli", "package.json")
|
|
3703
|
+
];
|
|
3704
|
+
try {
|
|
3705
|
+
const contents = await readFileImpl(binPath);
|
|
3706
|
+
for (const raw of extractDistIndexFromBinScript(contents)) {
|
|
3707
|
+
const distIndex = path16.resolve(binDir, expandBinDirVars(raw, binDir));
|
|
3708
|
+
candidates.push(packageJsonFromDistIndex(distIndex));
|
|
3709
|
+
}
|
|
3710
|
+
} catch {
|
|
3711
|
+
}
|
|
3712
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3713
|
+
for (const candidate2 of candidates) {
|
|
3714
|
+
const resolved = path16.resolve(candidate2);
|
|
3715
|
+
if (seen.has(resolved)) continue;
|
|
3716
|
+
seen.add(resolved);
|
|
3717
|
+
try {
|
|
3718
|
+
const version = parsePackageVersion(await readFileImpl(resolved));
|
|
3719
|
+
if (version) return version;
|
|
3720
|
+
} catch {
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
return null;
|
|
3724
|
+
}
|
|
3725
|
+
async function resolveBinOnPath(binName, env, platform) {
|
|
3663
3726
|
const pathVar = env.PATH ?? env.Path ?? "";
|
|
3664
|
-
if (!pathVar) return
|
|
3727
|
+
if (!pathVar) return null;
|
|
3665
3728
|
const dirs = pathVar.split(path16.delimiter).filter(Boolean);
|
|
3666
3729
|
const candidates = platform === "win32" ? [binName, `${binName}.cmd`, `${binName}.exe`, `${binName}.bat`] : [binName];
|
|
3667
3730
|
for (const dir of dirs) {
|
|
3668
3731
|
for (const candidate2 of candidates) {
|
|
3732
|
+
const abs = path16.join(dir, candidate2);
|
|
3669
3733
|
try {
|
|
3670
|
-
await access6(
|
|
3671
|
-
return
|
|
3734
|
+
await access6(abs, platform === "win32" ? void 0 : constants3.X_OK);
|
|
3735
|
+
return abs;
|
|
3672
3736
|
} catch {
|
|
3673
3737
|
}
|
|
3674
3738
|
}
|
|
3675
3739
|
}
|
|
3676
|
-
return
|
|
3740
|
+
return null;
|
|
3677
3741
|
}
|
|
3678
3742
|
function isNodeVersionOk(nodeVersion, minMajor = MIN_NODE_MAJOR) {
|
|
3679
3743
|
const match = /^v?(\d+)/.exec(nodeVersion);
|
|
@@ -3769,8 +3833,8 @@ async function assessEnvironment(options = {}) {
|
|
|
3769
3833
|
const nodeVersion = options.nodeVersion ?? process.version;
|
|
3770
3834
|
const homeDir = options.homeDir ?? homedir2();
|
|
3771
3835
|
const binName = options.binName ?? "agent-kit";
|
|
3772
|
-
const [
|
|
3773
|
-
|
|
3836
|
+
const [binPath, npmPrefix] = await Promise.all([
|
|
3837
|
+
resolveBinOnPath(binName, env, platform).catch(() => null),
|
|
3774
3838
|
checkNpmPrefixWritable(options).catch(
|
|
3775
3839
|
() => ({
|
|
3776
3840
|
prefix: null,
|
|
@@ -3779,8 +3843,11 @@ async function assessEnvironment(options = {}) {
|
|
|
3779
3843
|
})
|
|
3780
3844
|
)
|
|
3781
3845
|
]);
|
|
3846
|
+
const binVersion = binPath ? await readBinVersion(binPath, options).catch(() => null) : null;
|
|
3782
3847
|
return {
|
|
3783
|
-
binOnPath,
|
|
3848
|
+
binOnPath: binPath != null,
|
|
3849
|
+
binPath,
|
|
3850
|
+
binVersion,
|
|
3784
3851
|
npmPrefixWritable: npmPrefix.writable,
|
|
3785
3852
|
npmPrefix,
|
|
3786
3853
|
nodeVersionOk: isNodeVersionOk(nodeVersion),
|
|
@@ -5274,7 +5341,8 @@ function printDoctorSummary(result) {
|
|
|
5274
5341
|
}
|
|
5275
5342
|
}
|
|
5276
5343
|
console.log("environment:");
|
|
5277
|
-
|
|
5344
|
+
const pathLabel = result.env.binOnPath ? `ok (v${result.env.binVersion ?? "unknown"} at ${result.env.binPath})` : "MISSING";
|
|
5345
|
+
console.log(` - bin on PATH (agent-kit): ${pathLabel}`);
|
|
5278
5346
|
console.log(
|
|
5279
5347
|
` - npm prefix writable: ${result.env.npmPrefixWritable ? "ok" : "BLOCKED"}${result.env.npmPrefix.prefix ? ` (${result.env.npmPrefix.prefix})` : ""}`
|
|
5280
5348
|
);
|
|
@@ -6743,6 +6811,10 @@ var hookCommand = defineCommand10({
|
|
|
6743
6811
|
import { intro, outro } from "@clack/prompts";
|
|
6744
6812
|
import { defineCommand as defineCommand12 } from "citty";
|
|
6745
6813
|
|
|
6814
|
+
// src/lifecycle/path-cli.ts
|
|
6815
|
+
import { spawn as spawn6 } from "child_process";
|
|
6816
|
+
import path32 from "path";
|
|
6817
|
+
|
|
6746
6818
|
// src/utils/terminal.ts
|
|
6747
6819
|
import { readdir as readdir6 } from "fs/promises";
|
|
6748
6820
|
import { homedir as homedir3 } from "os";
|
|
@@ -6928,18 +7000,122 @@ function classifyInstallError(err) {
|
|
|
6928
7000
|
};
|
|
6929
7001
|
}
|
|
6930
7002
|
|
|
7003
|
+
// src/lifecycle/path-cli.ts
|
|
7004
|
+
function npxPinned(runtimeVersion, subcommand) {
|
|
7005
|
+
return `npx -y ${pinnedCliSpec(runtimeVersion)} ${subcommand}`;
|
|
7006
|
+
}
|
|
7007
|
+
function isBinUnderPrefix(binPath, prefix) {
|
|
7008
|
+
const bin = path32.resolve(binPath);
|
|
7009
|
+
const root = path32.resolve(prefix);
|
|
7010
|
+
return bin === root || bin.startsWith(`${root}${path32.sep}`);
|
|
7011
|
+
}
|
|
7012
|
+
function pathCliStatus(env, runtimeVersion) {
|
|
7013
|
+
if (!env.binOnPath || !env.binPath) return "missing";
|
|
7014
|
+
const running = normalizeSemver(runtimeVersion);
|
|
7015
|
+
const pathVer = env.binVersion ? normalizeSemver(env.binVersion) : null;
|
|
7016
|
+
if (!pathVer || !running) return "unknown";
|
|
7017
|
+
try {
|
|
7018
|
+
return compareSemver(pathVer, running) >= 0 ? "current" : "behind";
|
|
7019
|
+
} catch {
|
|
7020
|
+
return "unknown";
|
|
7021
|
+
}
|
|
7022
|
+
}
|
|
7023
|
+
function driftLines(env, runtimeVersion) {
|
|
7024
|
+
const pathVer = env.binVersion ?? "unknown";
|
|
7025
|
+
const where = env.binPath ?? "(unresolved)";
|
|
7026
|
+
return [
|
|
7027
|
+
`This CLI is v${runtimeVersion}. PATH \`agent-kit\` is v${pathVer} at:`,
|
|
7028
|
+
` ${where}`,
|
|
7029
|
+
"Do not run bare `agent-kit update` or `init` from that binary. It re-stamps the old version.",
|
|
7030
|
+
"Keep using the pinned npx form until PATH matches:",
|
|
7031
|
+
` ${npxPinned(runtimeVersion, "update")}`,
|
|
7032
|
+
` ${npxPinned(runtimeVersion, "status")}`
|
|
7033
|
+
];
|
|
7034
|
+
}
|
|
7035
|
+
function isShadow(env) {
|
|
7036
|
+
if (!env.binPath || !env.npmPrefix.prefix) return false;
|
|
7037
|
+
return !isBinUnderPrefix(env.binPath, env.npmPrefix.prefix);
|
|
7038
|
+
}
|
|
7039
|
+
async function spawnNpmGlobalInstall(spec) {
|
|
7040
|
+
return new Promise((resolve3) => {
|
|
7041
|
+
const child = spawn6("npm", ["i", "-g", spec], { stdio: "inherit" });
|
|
7042
|
+
child.on("error", (error) => resolve3({ ok: false, error }));
|
|
7043
|
+
child.on("close", (code) => {
|
|
7044
|
+
if (code === 0) resolve3({ ok: true });
|
|
7045
|
+
else resolve3({ ok: false, error: new Error(`npm exited with code ${code ?? "unknown"}`) });
|
|
7046
|
+
});
|
|
7047
|
+
});
|
|
7048
|
+
}
|
|
7049
|
+
async function syncPathCliToRuntime(options = {}) {
|
|
7050
|
+
const runtimeVersion = options.runtimeVersion ?? KIT_VERSION;
|
|
7051
|
+
const assess = options.assessEnvironmentImpl ?? assessEnvironment;
|
|
7052
|
+
let env = options.env ?? await assess();
|
|
7053
|
+
const autoInstall = options.autoInstall ?? !isNonInteractive();
|
|
7054
|
+
const lines = [];
|
|
7055
|
+
let status = pathCliStatus(env, runtimeVersion);
|
|
7056
|
+
if (status === "current") {
|
|
7057
|
+
return { status, env, upgraded: false, lines };
|
|
7058
|
+
}
|
|
7059
|
+
if (status === "behind" || status === "unknown") {
|
|
7060
|
+
lines.push(...driftLines(env, runtimeVersion));
|
|
7061
|
+
if (isShadow(env)) {
|
|
7062
|
+
lines.push(
|
|
7063
|
+
"That PATH hit is not npm's global bin, so `npm i -g` may not replace it.",
|
|
7064
|
+
"Run `hash -r` and `which -a agent-kit`. Put npm's global bin first, or remove the stale shim."
|
|
7065
|
+
);
|
|
7066
|
+
}
|
|
7067
|
+
}
|
|
7068
|
+
if (!autoInstall) {
|
|
7069
|
+
return { status, env, upgraded: false, lines };
|
|
7070
|
+
}
|
|
7071
|
+
if (status === "missing") {
|
|
7072
|
+
lines.push("No bare `agent-kit` on PATH yet (npx is ephemeral).");
|
|
7073
|
+
}
|
|
7074
|
+
if (!env.npmPrefixWritable) {
|
|
7075
|
+
lines.push(
|
|
7076
|
+
"npm's global prefix is not writable, so this process cannot upgrade PATH.",
|
|
7077
|
+
`Run ${npxPinned(runtimeVersion, "setup-global")} (or fix prefix permissions).`
|
|
7078
|
+
);
|
|
7079
|
+
return { status, env, upgraded: false, lines };
|
|
7080
|
+
}
|
|
7081
|
+
const spec = pinnedCliSpec(runtimeVersion);
|
|
7082
|
+
const install = options.npmInstallImpl ?? spawnNpmGlobalInstall;
|
|
7083
|
+
lines.push(`Installing ${spec} into the writable npm prefix...`);
|
|
7084
|
+
const outcome = await install(spec);
|
|
7085
|
+
if (!outcome.ok) {
|
|
7086
|
+
const detail = outcome.error instanceof Error ? outcome.error.message : "npm i -g failed";
|
|
7087
|
+
lines.push(`Global install failed: ${detail}`);
|
|
7088
|
+
return { status, env, upgraded: false, lines };
|
|
7089
|
+
}
|
|
7090
|
+
env = await assess();
|
|
7091
|
+
status = pathCliStatus(env, runtimeVersion);
|
|
7092
|
+
if (status === "current") {
|
|
7093
|
+
lines.push(
|
|
7094
|
+
`PATH \`agent-kit\` is now v${env.binVersion ?? runtimeVersion}.`,
|
|
7095
|
+
"If this shell still shows the old version, run `hash -r` or open a new terminal."
|
|
7096
|
+
);
|
|
7097
|
+
return { status, env, upgraded: true, lines };
|
|
7098
|
+
}
|
|
7099
|
+
lines.push(
|
|
7100
|
+
`Installed ${spec}, but PATH still resolves to v${env.binVersion ?? "unknown"} at:`,
|
|
7101
|
+
` ${env.binPath ?? "(unresolved)"}`,
|
|
7102
|
+
"Run `hash -r` and `which -a agent-kit`. Until PATH matches, keep using the npx pin above."
|
|
7103
|
+
);
|
|
7104
|
+
return { status, env, upgraded: true, lines };
|
|
7105
|
+
}
|
|
7106
|
+
|
|
6931
7107
|
// src/commands/install.ts
|
|
6932
|
-
import
|
|
7108
|
+
import path39 from "path";
|
|
6933
7109
|
import { defineCommand as defineCommand11 } from "citty";
|
|
6934
7110
|
import { bold, cyan as cyan3, green as green2, options as koloristOptions2 } from "kolorist";
|
|
6935
7111
|
|
|
6936
7112
|
// src/generator/personalization.ts
|
|
6937
7113
|
import { readFile as readFile19, writeFile as writeFile12 } from "fs/promises";
|
|
6938
|
-
import
|
|
7114
|
+
import path37 from "path";
|
|
6939
7115
|
|
|
6940
7116
|
// src/generator/claude-command-adapters.ts
|
|
6941
7117
|
import { readFile as readFile17, readdir as readdir7, writeFile as writeFile8 } from "fs/promises";
|
|
6942
|
-
import
|
|
7118
|
+
import path33 from "path";
|
|
6943
7119
|
var CURSOR_COMMANDS_DIR_REL = ".cursor/commands";
|
|
6944
7120
|
var CLAUDE_COMMANDS_DIR_REL = ".claude/commands";
|
|
6945
7121
|
var RESERVED_ADAPTER_NAMES = /* @__PURE__ */ new Set(["agent-kit"]);
|
|
@@ -6968,7 +7144,7 @@ Adapter rules (Claude Code CLI):
|
|
|
6968
7144
|
`;
|
|
6969
7145
|
}
|
|
6970
7146
|
async function discoverInstalledCommands(rootDir) {
|
|
6971
|
-
const dir =
|
|
7147
|
+
const dir = path33.join(rootDir, CURSOR_COMMANDS_DIR_REL);
|
|
6972
7148
|
let entries;
|
|
6973
7149
|
try {
|
|
6974
7150
|
entries = (await readdir7(dir)).filter((f) => f.endsWith(".md"));
|
|
@@ -6980,7 +7156,7 @@ async function discoverInstalledCommands(rootDir) {
|
|
|
6980
7156
|
const name = file.slice(0, -3);
|
|
6981
7157
|
if (RESERVED_ADAPTER_NAMES.has(name)) continue;
|
|
6982
7158
|
try {
|
|
6983
|
-
const raw = await readFile17(
|
|
7159
|
+
const raw = await readFile17(path33.join(dir, file), "utf8");
|
|
6984
7160
|
const parsed = parseCommandFrontmatter(name, raw);
|
|
6985
7161
|
if (parsed) commands.push(parsed);
|
|
6986
7162
|
} catch {
|
|
@@ -6995,11 +7171,11 @@ async function generateClaudeCommandAdapters(rootDir) {
|
|
|
6995
7171
|
const results = [];
|
|
6996
7172
|
let ledgerDirty = false;
|
|
6997
7173
|
for (const command of commands) {
|
|
6998
|
-
const relPath =
|
|
7174
|
+
const relPath = path33.posix.join(CLAUDE_COMMANDS_DIR_REL, `${command.name}.md`);
|
|
6999
7175
|
const rendered = renderClaudeCommandAdapter(command);
|
|
7000
|
-
const abs =
|
|
7176
|
+
const abs = path33.join(rootDir, relPath);
|
|
7001
7177
|
if (!await fileExists(abs)) {
|
|
7002
|
-
await ensureDir(
|
|
7178
|
+
await ensureDir(path33.dirname(abs));
|
|
7003
7179
|
await writeFile8(abs, rendered, "utf8");
|
|
7004
7180
|
ledger.hashes[relPath] = contentHash(rendered);
|
|
7005
7181
|
ledgerDirty = true;
|
|
@@ -7030,7 +7206,7 @@ async function generateClaudeCommandAdapters(rootDir) {
|
|
|
7030
7206
|
|
|
7031
7207
|
// src/generator/claude-kit-load.ts
|
|
7032
7208
|
import { writeFile as writeFile9 } from "fs/promises";
|
|
7033
|
-
import
|
|
7209
|
+
import path34 from "path";
|
|
7034
7210
|
var CLAUDE_MD_REL = "CLAUDE.md";
|
|
7035
7211
|
var AGENT_KIT_COMMAND_REL = ".claude/commands/agent-kit.md";
|
|
7036
7212
|
function renderClaudeMd() {
|
|
@@ -7086,11 +7262,11 @@ Non-goals: not audits / \`/plan-external-review\`, not a second tick dialect (\`
|
|
|
7086
7262
|
`;
|
|
7087
7263
|
}
|
|
7088
7264
|
async function writeUnlessExists(rootDir, relativePath, content) {
|
|
7089
|
-
const target =
|
|
7265
|
+
const target = path34.join(rootDir, relativePath);
|
|
7090
7266
|
if (await fileExists(target)) {
|
|
7091
7267
|
return { relativePath, status: "skipped-customized" };
|
|
7092
7268
|
}
|
|
7093
|
-
await ensureDir(
|
|
7269
|
+
await ensureDir(path34.dirname(target));
|
|
7094
7270
|
await writeFile9(target, content, "utf8");
|
|
7095
7271
|
return { relativePath, status: "applied" };
|
|
7096
7272
|
}
|
|
@@ -7103,7 +7279,7 @@ async function generateClaudeKitLoadArtifacts(rootDir) {
|
|
|
7103
7279
|
|
|
7104
7280
|
// src/generator/claude-session-start-hook.ts
|
|
7105
7281
|
import { readFile as readFile18, writeFile as writeFile10 } from "fs/promises";
|
|
7106
|
-
import
|
|
7282
|
+
import path35 from "path";
|
|
7107
7283
|
var CLAUDE_SETTINGS_REL = ".claude/settings.json";
|
|
7108
7284
|
var RESOLVE_AGENT_KIT_REL = ".cursor/hooks/agent/resolve-agent-kit.sh";
|
|
7109
7285
|
var SESSION_START_HOOK_MARKER = "hook session-start --format claude";
|
|
@@ -7178,7 +7354,7 @@ function instructionsBlock(entry) {
|
|
|
7178
7354
|
].join("\n");
|
|
7179
7355
|
}
|
|
7180
7356
|
async function writeClaudeSessionStartHook(rootDir) {
|
|
7181
|
-
const abs =
|
|
7357
|
+
const abs = path35.join(rootDir, CLAUDE_SETTINGS_REL);
|
|
7182
7358
|
let existing = null;
|
|
7183
7359
|
try {
|
|
7184
7360
|
existing = await readFile18(abs, "utf8");
|
|
@@ -7196,14 +7372,14 @@ async function writeClaudeSessionStartHook(rootDir) {
|
|
|
7196
7372
|
if (merged.status === "unchanged") {
|
|
7197
7373
|
return { relativePath: CLAUDE_SETTINGS_REL, status: "unchanged" };
|
|
7198
7374
|
}
|
|
7199
|
-
await ensureDir(
|
|
7375
|
+
await ensureDir(path35.dirname(abs));
|
|
7200
7376
|
await writeFile10(abs, merged.content, "utf8");
|
|
7201
7377
|
return { relativePath: CLAUDE_SETTINGS_REL, status: merged.status };
|
|
7202
7378
|
}
|
|
7203
7379
|
|
|
7204
7380
|
// src/generator/vscode.ts
|
|
7205
7381
|
import { writeFile as writeFile11 } from "fs/promises";
|
|
7206
|
-
import
|
|
7382
|
+
import path36 from "path";
|
|
7207
7383
|
|
|
7208
7384
|
// src/generator/platform.ts
|
|
7209
7385
|
function gitProviderLabel(profile) {
|
|
@@ -7227,10 +7403,10 @@ function prTerminology(profile) {
|
|
|
7227
7403
|
// src/generator/vscode.ts
|
|
7228
7404
|
async function generateVSCodeArtifacts(profile) {
|
|
7229
7405
|
const results = [];
|
|
7230
|
-
const vscodeDir =
|
|
7231
|
-
const githubDir =
|
|
7406
|
+
const vscodeDir = path36.join(profile.rootDir, ".vscode");
|
|
7407
|
+
const githubDir = path36.join(profile.rootDir, ".github");
|
|
7232
7408
|
await Promise.all([ensureDir(vscodeDir), ensureDir(githubDir)]);
|
|
7233
|
-
const settingsPath =
|
|
7409
|
+
const settingsPath = path36.join(vscodeDir, "settings.json");
|
|
7234
7410
|
if (await fileExists(settingsPath)) {
|
|
7235
7411
|
results.push({ relativePath: ".vscode/settings.json", status: "skipped-customized" });
|
|
7236
7412
|
} else {
|
|
@@ -7254,7 +7430,7 @@ async function generateVSCodeArtifacts(profile) {
|
|
|
7254
7430
|
}
|
|
7255
7431
|
const provider = gitProviderLabel(profile);
|
|
7256
7432
|
const prTerm = prTerminology(profile);
|
|
7257
|
-
const copilotPath =
|
|
7433
|
+
const copilotPath = path36.join(githubDir, "copilot-instructions.md");
|
|
7258
7434
|
if (await fileExists(copilotPath)) {
|
|
7259
7435
|
results.push({ relativePath: ".github/copilot-instructions.md", status: "skipped-customized" });
|
|
7260
7436
|
} else {
|
|
@@ -7272,7 +7448,7 @@ async function generateVSCodeArtifacts(profile) {
|
|
|
7272
7448
|
results.push({ relativePath: ".github/copilot-instructions.md", status: "applied" });
|
|
7273
7449
|
}
|
|
7274
7450
|
if (profile.ide.plan === "vscode-pro") {
|
|
7275
|
-
const securityPath =
|
|
7451
|
+
const securityPath = path36.join(vscodeDir, "security-review.agent.md");
|
|
7276
7452
|
if (await fileExists(securityPath)) {
|
|
7277
7453
|
results.push({
|
|
7278
7454
|
relativePath: ".vscode/security-review.agent.md",
|
|
@@ -7484,7 +7660,7 @@ function renderProjectContext(profile, skillItems = []) {
|
|
|
7484
7660
|
`;
|
|
7485
7661
|
}
|
|
7486
7662
|
async function createOwnedFile(rootDir, relativePath, content, evidence) {
|
|
7487
|
-
const target =
|
|
7663
|
+
const target = path37.join(rootDir, relativePath);
|
|
7488
7664
|
if (await fileExists(target)) {
|
|
7489
7665
|
return {
|
|
7490
7666
|
kind: "file",
|
|
@@ -7494,7 +7670,7 @@ async function createOwnedFile(rootDir, relativePath, content, evidence) {
|
|
|
7494
7670
|
evidence
|
|
7495
7671
|
};
|
|
7496
7672
|
}
|
|
7497
|
-
await ensureDir(
|
|
7673
|
+
await ensureDir(path37.dirname(target));
|
|
7498
7674
|
await writeFile12(target, content, "utf8");
|
|
7499
7675
|
return {
|
|
7500
7676
|
kind: "file",
|
|
@@ -7511,7 +7687,7 @@ async function packTargets(registryRoot, packId) {
|
|
|
7511
7687
|
async function existingTargets(projectRoot, targets) {
|
|
7512
7688
|
const checks = await Promise.all(
|
|
7513
7689
|
targets.map(
|
|
7514
|
-
async (target) => await fileExists(
|
|
7690
|
+
async (target) => await fileExists(path37.join(projectRoot, target)) ? target : null
|
|
7515
7691
|
)
|
|
7516
7692
|
);
|
|
7517
7693
|
return checks.filter((target) => target !== null);
|
|
@@ -7533,14 +7709,14 @@ async function applyPersonalization(input) {
|
|
|
7533
7709
|
componentResults.push({ ...item, status: "unavailable" });
|
|
7534
7710
|
continue;
|
|
7535
7711
|
}
|
|
7536
|
-
const target =
|
|
7712
|
+
const target = path37.posix.join(
|
|
7537
7713
|
".cursor",
|
|
7538
7714
|
"skills",
|
|
7539
7715
|
skill.path.includes("/core/") ? "core" : "community",
|
|
7540
7716
|
skill.id,
|
|
7541
7717
|
"SKILL.md"
|
|
7542
7718
|
);
|
|
7543
|
-
if (await fileExists(
|
|
7719
|
+
if (await fileExists(path37.join(input.rootDir, target))) {
|
|
7544
7720
|
componentResults.push({ ...item, status: "skipped-customized", path: target });
|
|
7545
7721
|
protectedPaths.add(target);
|
|
7546
7722
|
continue;
|
|
@@ -7685,7 +7861,7 @@ async function applyPersonalization(input) {
|
|
|
7685
7861
|
protectedPaths: [...protectedPaths].sort(),
|
|
7686
7862
|
...claudeSessionStartInstructions ? { claudeSessionStartInstructions } : {}
|
|
7687
7863
|
};
|
|
7688
|
-
await writeJson(
|
|
7864
|
+
await writeJson(path37.join(input.rootDir, RESULT_PATH), result);
|
|
7689
7865
|
return {
|
|
7690
7866
|
result,
|
|
7691
7867
|
manifest: {
|
|
@@ -7703,7 +7879,7 @@ async function applyPersonalization(input) {
|
|
|
7703
7879
|
};
|
|
7704
7880
|
}
|
|
7705
7881
|
async function readRepositoryProfile(rootDir) {
|
|
7706
|
-
const target =
|
|
7882
|
+
const target = path37.join(rootDir, ".cursor/agent-kit.config.json");
|
|
7707
7883
|
if (!await fileExists(target)) return null;
|
|
7708
7884
|
return JSON.parse(await readFile19(target, "utf8"));
|
|
7709
7885
|
}
|
|
@@ -7711,16 +7887,16 @@ async function readRepositoryProfile(rootDir) {
|
|
|
7711
7887
|
// src/lifecycle/onboard-migration.ts
|
|
7712
7888
|
import { createHash as createHash4 } from "crypto";
|
|
7713
7889
|
import { readFile as readFile20, unlink } from "fs/promises";
|
|
7714
|
-
import
|
|
7890
|
+
import path38 from "path";
|
|
7715
7891
|
var LEGACY_ONBOARD_PATH = ".cursor/commands/onboard.md";
|
|
7716
7892
|
var NAMESPACED_ONBOARD_PATH = ".cursor/commands/agent-kit-onboard.md";
|
|
7717
7893
|
var MANAGED_LEGACY_HASHES = /* @__PURE__ */ new Set([
|
|
7718
7894
|
"b274a68941813f19b185893cb7c5561dff027f53270890029992f208e24992fe"
|
|
7719
7895
|
]);
|
|
7720
7896
|
async function migrateLegacyOnboardCommand(projectRoot, managedHashes = MANAGED_LEGACY_HASHES) {
|
|
7721
|
-
const legacyPath =
|
|
7897
|
+
const legacyPath = path38.join(projectRoot, LEGACY_ONBOARD_PATH);
|
|
7722
7898
|
if (!await fileExists(legacyPath)) return "absent";
|
|
7723
|
-
const namespacedPath =
|
|
7899
|
+
const namespacedPath = path38.join(projectRoot, NAMESPACED_ONBOARD_PATH);
|
|
7724
7900
|
if (!await fileExists(namespacedPath)) return "preserved-customized";
|
|
7725
7901
|
const content = await readFile20(legacyPath);
|
|
7726
7902
|
const hash = createHash4("sha256").update(content).digest("hex");
|
|
@@ -7810,8 +7986,15 @@ function paint(fn, text) {
|
|
|
7810
7986
|
function printInstallEpilogue(env, options = {}) {
|
|
7811
7987
|
const print = options.print ?? ((line) => console.log(line));
|
|
7812
7988
|
const color = options.color ?? shouldUseWelcomeColor();
|
|
7813
|
-
|
|
7814
|
-
|
|
7989
|
+
const runtimeVersion = options.runtimeVersion ?? KIT_VERSION;
|
|
7990
|
+
const status = pathCliStatus(env, runtimeVersion);
|
|
7991
|
+
if (status === "current") {
|
|
7992
|
+
const line = `PATH \`agent-kit\` is v${env.binVersion ?? runtimeVersion}. Run it directly, e.g. \`agent-kit doctor\`.`;
|
|
7993
|
+
print(color ? paint(green2, line) : line);
|
|
7994
|
+
return;
|
|
7995
|
+
}
|
|
7996
|
+
if (status === "behind" || status === "unknown") {
|
|
7997
|
+
const line = `Keep using ${npxPinned(runtimeVersion, "<subcommand>")} until PATH is v${runtimeVersion}.`;
|
|
7815
7998
|
print(color ? paint(green2, line) : line);
|
|
7816
7999
|
return;
|
|
7817
8000
|
}
|
|
@@ -7821,11 +8004,11 @@ function printInstallEpilogue(env, options = {}) {
|
|
|
7821
8004
|
'If you try `agent-kit <subcommand>` next, you will see "command not',
|
|
7822
8005
|
'found". Pick one:',
|
|
7823
8006
|
"",
|
|
7824
|
-
" 1. Keep using npx
|
|
7825
|
-
|
|
8007
|
+
" 1. Keep using npx (works right now, no action needed)",
|
|
8008
|
+
` ${npxPinned(runtimeVersion, "<subcommand>")}`,
|
|
7826
8009
|
"",
|
|
7827
8010
|
" 2. Put a bare `agent-kit` on PATH",
|
|
7828
|
-
|
|
8011
|
+
` ${npxPinned(runtimeVersion, "setup-global")}`,
|
|
7829
8012
|
" (fixes a root-owned npm prefix if that's the blocker, or just installs)",
|
|
7830
8013
|
"",
|
|
7831
8014
|
" 3. Manual steps",
|
|
@@ -7833,7 +8016,7 @@ function printInstallEpilogue(env, options = {}) {
|
|
|
7833
8016
|
" mkdir -p ~/.npm-global",
|
|
7834
8017
|
' npm config set prefix "~/.npm-global"',
|
|
7835
8018
|
' export PATH="~/.npm-global/bin:$PATH"',
|
|
7836
|
-
|
|
8019
|
+
` npm i -g ${pinnedCliSpec(runtimeVersion)}`
|
|
7837
8020
|
];
|
|
7838
8021
|
print(color ? paint(cyan3, divider) : divider);
|
|
7839
8022
|
const heading = "Heads up: a bare `agent-kit` command won't work yet";
|
|
@@ -7844,10 +8027,12 @@ function printInstallEpilogue(env, options = {}) {
|
|
|
7844
8027
|
async function printPostInstallSummary(result) {
|
|
7845
8028
|
printReadinessNarrative(result);
|
|
7846
8029
|
const env = await assessEnvironment();
|
|
7847
|
-
|
|
8030
|
+
const sync = await syncPathCliToRuntime({ runtimeVersion: KIT_VERSION, env });
|
|
8031
|
+
for (const line of sync.lines) console.log(line);
|
|
8032
|
+
printInstallEpilogue(sync.env, { runtimeVersion: KIT_VERSION });
|
|
7848
8033
|
}
|
|
7849
8034
|
async function performInstall(options) {
|
|
7850
|
-
const projectRoot =
|
|
8035
|
+
const projectRoot = path39.resolve(options.cwd);
|
|
7851
8036
|
const packs = parsePackList(options.pack);
|
|
7852
8037
|
const existing = await loadAgentKitManifest(projectRoot);
|
|
7853
8038
|
const registry = await resolveRegistryFromCli({
|
|
@@ -7970,6 +8155,7 @@ ${err.recovery}
|
|
|
7970
8155
|
throw err;
|
|
7971
8156
|
}
|
|
7972
8157
|
logger.info(`Installing into: ${projectRoot}`);
|
|
8158
|
+
logger.info(`CLI v${KIT_VERSION}`);
|
|
7973
8159
|
await warnIfRunningCliBehindNpm(projectRoot, { warn: (message) => logger.warn(message) });
|
|
7974
8160
|
const packs = parsePackList(args.pack);
|
|
7975
8161
|
for (const id of packs) {
|
|
@@ -8072,12 +8258,13 @@ ${err.recovery}
|
|
|
8072
8258
|
logger.success(`L0 and readiness prepared in ${result.projectRoot}`);
|
|
8073
8259
|
const nextStep = nextStepAfterInstall(pending);
|
|
8074
8260
|
const env = await assessEnvironment();
|
|
8261
|
+
const sync = await syncPathCliToRuntime({ runtimeVersion: KIT_VERSION, env });
|
|
8262
|
+
for (const line of sync.lines) console.log(line);
|
|
8263
|
+
printInstallEpilogue(sync.env, { runtimeVersion: KIT_VERSION });
|
|
8075
8264
|
if (!nonInteractive) {
|
|
8076
|
-
printInstallEpilogue(env);
|
|
8077
8265
|
outro(nextStep);
|
|
8078
8266
|
} else {
|
|
8079
8267
|
logger.info(nextStep);
|
|
8080
|
-
printInstallEpilogue(env);
|
|
8081
8268
|
}
|
|
8082
8269
|
} catch (err) {
|
|
8083
8270
|
const hint = classifyInstallError(err);
|
|
@@ -8250,7 +8437,7 @@ function shouldLiveRefresh(opts) {
|
|
|
8250
8437
|
// src/mission-control/snapshot.ts
|
|
8251
8438
|
import { execFile as execFile6 } from "child_process";
|
|
8252
8439
|
import { access as access8 } from "fs/promises";
|
|
8253
|
-
import
|
|
8440
|
+
import path40 from "path";
|
|
8254
8441
|
|
|
8255
8442
|
// ../../dashboard/lib/live-refresh.mjs
|
|
8256
8443
|
import { join, resolve as resolve2 } from "path";
|
|
@@ -8283,7 +8470,7 @@ async function firstExisting2(candidates) {
|
|
|
8283
8470
|
for (const candidate2 of candidates) {
|
|
8284
8471
|
try {
|
|
8285
8472
|
await access8(candidate2);
|
|
8286
|
-
return
|
|
8473
|
+
return path40.resolve(candidate2);
|
|
8287
8474
|
} catch {
|
|
8288
8475
|
}
|
|
8289
8476
|
}
|
|
@@ -8292,7 +8479,7 @@ async function firstExisting2(candidates) {
|
|
|
8292
8479
|
async function findDashboardDataScript(cwd, env = process.env, options = {}) {
|
|
8293
8480
|
const startPath = await findDashboardStart(cwd, env, options);
|
|
8294
8481
|
if (startPath) {
|
|
8295
|
-
const sibling =
|
|
8482
|
+
const sibling = path40.join(path40.dirname(startPath), "dashboard-data.mjs");
|
|
8296
8483
|
try {
|
|
8297
8484
|
await access8(sibling);
|
|
8298
8485
|
return sibling;
|
|
@@ -8307,7 +8494,7 @@ async function loadDashboardSnapshot(opts) {
|
|
|
8307
8494
|
const env = opts.env ?? process.env;
|
|
8308
8495
|
const timeout = dataScriptTimeoutMs(env);
|
|
8309
8496
|
const run = opts.execFileFn ?? execFile6;
|
|
8310
|
-
const snapshotRoot =
|
|
8497
|
+
const snapshotRoot = path40.resolve(opts.snapshotRoot);
|
|
8311
8498
|
return new Promise((resolve3) => {
|
|
8312
8499
|
run(
|
|
8313
8500
|
process.execPath,
|
|
@@ -8615,13 +8802,13 @@ var missionControlCommand = defineCommand13({
|
|
|
8615
8802
|
});
|
|
8616
8803
|
|
|
8617
8804
|
// src/commands/monitors.ts
|
|
8618
|
-
import
|
|
8805
|
+
import path42 from "path";
|
|
8619
8806
|
import { defineCommand as defineCommand14 } from "citty";
|
|
8620
8807
|
|
|
8621
8808
|
// src/invariants/monitors-untriaged.ts
|
|
8622
8809
|
import { execFile as execFile7 } from "child_process";
|
|
8623
8810
|
import { readFile as readFile21, readdir as readdir8, stat as stat5 } from "fs/promises";
|
|
8624
|
-
import
|
|
8811
|
+
import path41 from "path";
|
|
8625
8812
|
import { promisify as promisify6 } from "util";
|
|
8626
8813
|
|
|
8627
8814
|
// src/invariants/triage-heading.ts
|
|
@@ -8662,7 +8849,7 @@ async function gitFreshMonitorNames(rootDir) {
|
|
|
8662
8849
|
for (const line of stdout.split("\n")) {
|
|
8663
8850
|
if (!line.trim()) continue;
|
|
8664
8851
|
const file = line.slice(3).trim().replace(/^.* -> /, "");
|
|
8665
|
-
const base =
|
|
8852
|
+
const base = path41.basename(file);
|
|
8666
8853
|
if (base.startsWith("plan-monitor-") && base.endsWith(".md")) {
|
|
8667
8854
|
names.add(base);
|
|
8668
8855
|
}
|
|
@@ -8685,13 +8872,13 @@ function monitorSlugFromName(fileName) {
|
|
|
8685
8872
|
return fileName.replace(/^plan-monitor-/, "").replace(/\.md$/, "").toLowerCase();
|
|
8686
8873
|
}
|
|
8687
8874
|
async function selectUntriagedMonitors(rootDir) {
|
|
8688
|
-
const root =
|
|
8689
|
-
const memoryDir =
|
|
8875
|
+
const root = path41.resolve(rootDir);
|
|
8876
|
+
const memoryDir = path41.join(root, ".cursor", "memory");
|
|
8690
8877
|
const allNames = await listMonitorFiles(memoryDir);
|
|
8691
8878
|
const selectionOrder = ["git-fresh", "handoff-aligned", "untriaged-scan"];
|
|
8692
8879
|
const byName = /* @__PURE__ */ new Map();
|
|
8693
8880
|
for (const name of allNames) {
|
|
8694
|
-
const abs =
|
|
8881
|
+
const abs = path41.join(memoryDir, name);
|
|
8695
8882
|
try {
|
|
8696
8883
|
const [content, st] = await Promise.all([readFile21(abs, "utf8"), stat5(abs)]);
|
|
8697
8884
|
byName.set(name, { content, mtimeMs: st.mtimeMs });
|
|
@@ -8706,7 +8893,7 @@ async function selectUntriagedMonitors(rootDir) {
|
|
|
8706
8893
|
const gitFreshSet = [...gitFresh].filter(untriaged).sort();
|
|
8707
8894
|
let handoff = "";
|
|
8708
8895
|
try {
|
|
8709
|
-
handoff = await readFile21(
|
|
8896
|
+
handoff = await readFile21(path41.join(root, ".cursor", "HANDOFF.md"), "utf8");
|
|
8710
8897
|
} catch {
|
|
8711
8898
|
handoff = "";
|
|
8712
8899
|
}
|
|
@@ -8726,8 +8913,8 @@ async function selectUntriagedMonitors(rootDir) {
|
|
|
8726
8913
|
const row = byName.get(name);
|
|
8727
8914
|
if (!row) continue;
|
|
8728
8915
|
entries.push({
|
|
8729
|
-
path:
|
|
8730
|
-
relativePath:
|
|
8916
|
+
path: path41.join(memoryDir, name),
|
|
8917
|
+
relativePath: path41.relative(root, path41.join(memoryDir, name)).split(path41.sep).join("/"),
|
|
8731
8918
|
mtimeMs: row.mtimeMs,
|
|
8732
8919
|
hasTriageHeading: false,
|
|
8733
8920
|
hasOpenGaps: hasOpenGaps(row.content),
|
|
@@ -8773,7 +8960,7 @@ var monitorsCommand = defineCommand14({
|
|
|
8773
8960
|
process.exitCode = 2;
|
|
8774
8961
|
return;
|
|
8775
8962
|
}
|
|
8776
|
-
const result = await selectUntriagedMonitors(
|
|
8963
|
+
const result = await selectUntriagedMonitors(path42.resolve(args.cwd));
|
|
8777
8964
|
if (args.json) {
|
|
8778
8965
|
console.log(JSON.stringify(result, null, 2));
|
|
8779
8966
|
return;
|
|
@@ -8789,7 +8976,7 @@ var monitorsCommand = defineCommand14({
|
|
|
8789
8976
|
});
|
|
8790
8977
|
|
|
8791
8978
|
// src/commands/plan-index.ts
|
|
8792
|
-
import
|
|
8979
|
+
import path43 from "path";
|
|
8793
8980
|
import { defineCommand as defineCommand15 } from "citty";
|
|
8794
8981
|
var planIndexCommand = defineCommand15({
|
|
8795
8982
|
meta: {
|
|
@@ -8808,7 +8995,7 @@ var planIndexCommand = defineCommand15({
|
|
|
8808
8995
|
}
|
|
8809
8996
|
},
|
|
8810
8997
|
async run({ args }) {
|
|
8811
|
-
const root =
|
|
8998
|
+
const root = path43.resolve(args.cwd);
|
|
8812
8999
|
const index = await writePlanIndex(root);
|
|
8813
9000
|
if (args.json) {
|
|
8814
9001
|
console.log(JSON.stringify(index, null, 2));
|
|
@@ -8824,14 +9011,14 @@ var planIndexCommand = defineCommand15({
|
|
|
8824
9011
|
});
|
|
8825
9012
|
|
|
8826
9013
|
// src/commands/run-plan.ts
|
|
8827
|
-
import
|
|
9014
|
+
import path49 from "path";
|
|
8828
9015
|
import { defineCommand as defineCommand16 } from "citty";
|
|
8829
9016
|
|
|
8830
9017
|
// src/plan-loop/backends.ts
|
|
8831
|
-
import { execFileSync as execFileSync2, spawn as
|
|
9018
|
+
import { execFileSync as execFileSync2, spawn as spawn7 } from "child_process";
|
|
8832
9019
|
import { createWriteStream } from "fs";
|
|
8833
9020
|
import { access as access9 } from "fs/promises";
|
|
8834
|
-
import
|
|
9021
|
+
import path44 from "path";
|
|
8835
9022
|
import { StringDecoder } from "string_decoder";
|
|
8836
9023
|
var CLAUDE_ENV_PASSTHROUGH = [
|
|
8837
9024
|
"ANTHROPIC_BASE_URL",
|
|
@@ -8987,7 +9174,7 @@ async function whichBinary(bin) {
|
|
|
8987
9174
|
}
|
|
8988
9175
|
}
|
|
8989
9176
|
function spawnLogged(command, args, logPath, options = {}) {
|
|
8990
|
-
const spawnFn = options.spawnFn ??
|
|
9177
|
+
const spawnFn = options.spawnFn ?? spawn7;
|
|
8991
9178
|
const redact = options.redact ?? [];
|
|
8992
9179
|
const redactedError = (err) => new Error(redactSecrets(String(err), redact));
|
|
8993
9180
|
return new Promise((resolve3, reject) => {
|
|
@@ -9141,9 +9328,9 @@ function claudeHeadlessArgs(opts) {
|
|
|
9141
9328
|
async function missingClaudeAdapter(workspace, prompt) {
|
|
9142
9329
|
const m = /^\/([A-Za-z0-9][A-Za-z0-9_-]*)/.exec(prompt.trimStart());
|
|
9143
9330
|
if (!m?.[1]) return null;
|
|
9144
|
-
const rel =
|
|
9331
|
+
const rel = path44.join(".claude", "commands", `${m[1]}.md`);
|
|
9145
9332
|
try {
|
|
9146
|
-
await access9(
|
|
9333
|
+
await access9(path44.join(workspace, rel));
|
|
9147
9334
|
return null;
|
|
9148
9335
|
} catch {
|
|
9149
9336
|
return rel;
|
|
@@ -9259,13 +9446,13 @@ async function detectAgentBackend(requested, whichFn = whichBinary) {
|
|
|
9259
9446
|
|
|
9260
9447
|
// src/plan-loop/run-loop.ts
|
|
9261
9448
|
import { mkdir as mkdir6, readFile as readFile24, rm as rm2, unlink as unlink2 } from "fs/promises";
|
|
9262
|
-
import
|
|
9449
|
+
import path48 from "path";
|
|
9263
9450
|
|
|
9264
9451
|
// src/plan-loop/external-review.ts
|
|
9265
|
-
import { spawn as
|
|
9266
|
-
import
|
|
9267
|
-
var CANONICAL_REL =
|
|
9268
|
-
var FALLBACK_REL =
|
|
9452
|
+
import { spawn as spawn8 } from "child_process";
|
|
9453
|
+
import path45 from "path";
|
|
9454
|
+
var CANONICAL_REL = path45.join(".cursor", "scripts", "plan-external-review.sh");
|
|
9455
|
+
var FALLBACK_REL = path45.join("scripts", "plan-external-review.sh");
|
|
9269
9456
|
function isPlanExhaustedReason(reason) {
|
|
9270
9457
|
const r = reason.trim().toLowerCase();
|
|
9271
9458
|
if (!r) return false;
|
|
@@ -9283,12 +9470,12 @@ function shouldArmExternalPlanReview(input) {
|
|
|
9283
9470
|
return false;
|
|
9284
9471
|
}
|
|
9285
9472
|
async function armExternalPlanReview(root, options = {}) {
|
|
9286
|
-
const spawnFn = options.spawnFn ??
|
|
9473
|
+
const spawnFn = options.spawnFn ?? spawn8;
|
|
9287
9474
|
const existsFn = options.existsFn ?? fileExists;
|
|
9288
9475
|
const log = options.log ?? ((line) => console.log(line));
|
|
9289
9476
|
const force = options.force === true;
|
|
9290
|
-
const canonicalPath =
|
|
9291
|
-
const fallbackPath =
|
|
9477
|
+
const canonicalPath = path45.join(root, CANONICAL_REL);
|
|
9478
|
+
const fallbackPath = path45.join(root, FALLBACK_REL);
|
|
9292
9479
|
let scriptPath = null;
|
|
9293
9480
|
let scriptRel = CANONICAL_REL;
|
|
9294
9481
|
if (await existsFn(canonicalPath)) {
|
|
@@ -9341,7 +9528,7 @@ async function armExternalPlanReview(root, options = {}) {
|
|
|
9341
9528
|
}
|
|
9342
9529
|
|
|
9343
9530
|
// src/plan-loop/persona-banners.ts
|
|
9344
|
-
import
|
|
9531
|
+
import path46 from "path";
|
|
9345
9532
|
import {
|
|
9346
9533
|
blue,
|
|
9347
9534
|
cyan as cyan4,
|
|
@@ -9377,7 +9564,7 @@ function resolveColor(name, fallback) {
|
|
|
9377
9564
|
async function resolveCliPersonaId(root) {
|
|
9378
9565
|
try {
|
|
9379
9566
|
const cfg = await readJson(
|
|
9380
|
-
|
|
9567
|
+
path46.join(root, ".cursor", "context", "config.json")
|
|
9381
9568
|
);
|
|
9382
9569
|
const modes = cfg?.agentPersona?.modes ?? cfg?.workspaceSkin?.modes;
|
|
9383
9570
|
const id = modes?.[CLI_RUN_PLAN_MODE];
|
|
@@ -9388,7 +9575,7 @@ async function resolveCliPersonaId(root) {
|
|
|
9388
9575
|
}
|
|
9389
9576
|
async function loadPersonaPack(root, personaId) {
|
|
9390
9577
|
try {
|
|
9391
|
-
const personaPath =
|
|
9578
|
+
const personaPath = path46.join(root, "registry", "personas", "core", personaId, "persona.json");
|
|
9392
9579
|
const pack = await readJson(personaPath);
|
|
9393
9580
|
if (!pack || typeof pack.id !== "string") return null;
|
|
9394
9581
|
return pack;
|
|
@@ -9438,7 +9625,7 @@ function createPersonaBannerPrinter(persona) {
|
|
|
9438
9625
|
|
|
9439
9626
|
// src/plan-loop/plan-state.ts
|
|
9440
9627
|
import { readFile as readFile22, readdir as readdir9 } from "fs/promises";
|
|
9441
|
-
import
|
|
9628
|
+
import path47 from "path";
|
|
9442
9629
|
function countPendingTodos(raw) {
|
|
9443
9630
|
const lines = raw.split(/\r?\n/);
|
|
9444
9631
|
let inFront = 0;
|
|
@@ -9466,7 +9653,7 @@ function countPendingTodos(raw) {
|
|
|
9466
9653
|
async function findActivePlanFile(plansDir) {
|
|
9467
9654
|
if (!await fileExists(plansDir)) return null;
|
|
9468
9655
|
const files = (await readdir9(plansDir)).filter((f) => f.endsWith(".plan.md")).sort();
|
|
9469
|
-
return files[0] ?
|
|
9656
|
+
return files[0] ? path47.join(plansDir, files[0]) : null;
|
|
9470
9657
|
}
|
|
9471
9658
|
async function readPlan(planPath) {
|
|
9472
9659
|
return readFile22(planPath, "utf8");
|
|
@@ -9569,9 +9756,9 @@ function sleep(ms) {
|
|
|
9569
9756
|
return new Promise((r) => setTimeout(r, ms));
|
|
9570
9757
|
}
|
|
9571
9758
|
async function runPlanLoop(opts) {
|
|
9572
|
-
const plansDir =
|
|
9573
|
-
const stopFile =
|
|
9574
|
-
const logDir =
|
|
9759
|
+
const plansDir = path48.join(opts.root, ".cursor", "plans");
|
|
9760
|
+
const stopFile = path48.join(opts.root, ".cursor", "loop.stop");
|
|
9761
|
+
const logDir = path48.join(opts.root, ".cursor", "loop-logs");
|
|
9575
9762
|
const planPath = await findActivePlanFile(plansDir);
|
|
9576
9763
|
if (!planPath) {
|
|
9577
9764
|
logger.error("No active plan in .cursor/plans/");
|
|
@@ -9592,7 +9779,7 @@ async function runPlanLoop(opts) {
|
|
|
9592
9779
|
try {
|
|
9593
9780
|
const persona = await loadCliRunPlanPersona(opts.root);
|
|
9594
9781
|
const banners = createPersonaBannerPrinter(persona);
|
|
9595
|
-
console.log(`Active plan: ${
|
|
9782
|
+
console.log(`Active plan: ${path48.basename(planPath)}`);
|
|
9596
9783
|
console.log(`Pending to-dos: ${await pending()} | max ticks: ${opts.maxTicks}`);
|
|
9597
9784
|
console.log(`Backend: ${opts.backend.id}`);
|
|
9598
9785
|
if (persona) {
|
|
@@ -9635,8 +9822,8 @@ async function runPlanLoop(opts) {
|
|
|
9635
9822
|
planExhausted = true;
|
|
9636
9823
|
break;
|
|
9637
9824
|
}
|
|
9638
|
-
const logPath =
|
|
9639
|
-
const relLog =
|
|
9825
|
+
const logPath = path48.join(logDir, `tick-${stamp()}.log`);
|
|
9826
|
+
const relLog = path48.relative(opts.root, logPath);
|
|
9640
9827
|
console.log("");
|
|
9641
9828
|
const tickLine = `=== tick ${tick}/${opts.maxTicks} - pending: ${before} - log: ${relLog} ===`;
|
|
9642
9829
|
if (banners) banners.tickStart(tickLine);
|
|
@@ -9727,7 +9914,7 @@ async function runPlanLoop(opts) {
|
|
|
9727
9914
|
const finishDetail = `after ${tick} tick(s); pending: ${pendingNow}`;
|
|
9728
9915
|
if (banners) banners.phaseComplete(finishDetail);
|
|
9729
9916
|
console.log(
|
|
9730
|
-
`Loop finished after ${tick} tick(s). Pending now: ${pendingNow}. Logs in ${
|
|
9917
|
+
`Loop finished after ${tick} tick(s). Pending now: ${pendingNow}. Logs in ${path48.relative(opts.root, logDir)}/`
|
|
9731
9918
|
);
|
|
9732
9919
|
if (planExhausted || shouldArmExternalPlanReview({ pending: pendingNow, stopReason })) {
|
|
9733
9920
|
await armExternalPlanReview(opts.root);
|
|
@@ -9809,7 +9996,7 @@ var runPlanCommand = defineCommand16({
|
|
|
9809
9996
|
return;
|
|
9810
9997
|
}
|
|
9811
9998
|
const code = await runPlanLoop({
|
|
9812
|
-
root:
|
|
9999
|
+
root: path49.resolve(args.cwd),
|
|
9813
10000
|
maxTicks,
|
|
9814
10001
|
sleepSeconds,
|
|
9815
10002
|
model: args.model ? String(args.model) : void 0,
|
|
@@ -9822,12 +10009,12 @@ var runPlanCommand = defineCommand16({
|
|
|
9822
10009
|
|
|
9823
10010
|
// src/commands/run.ts
|
|
9824
10011
|
import { homedir as homedir4 } from "os";
|
|
9825
|
-
import
|
|
10012
|
+
import path51 from "path";
|
|
9826
10013
|
import { defineCommand as defineCommand17 } from "citty";
|
|
9827
10014
|
|
|
9828
10015
|
// src/plan-loop/dispatch.ts
|
|
9829
10016
|
import { mkdir as mkdir7, readFile as readFile25 } from "fs/promises";
|
|
9830
|
-
import
|
|
10017
|
+
import path50 from "path";
|
|
9831
10018
|
var RUN_CATALOG = [
|
|
9832
10019
|
"run-plan",
|
|
9833
10020
|
"run-plan-all",
|
|
@@ -9840,6 +10027,7 @@ var RUN_CATALOG = [
|
|
|
9840
10027
|
"git-staging",
|
|
9841
10028
|
"kit-staging"
|
|
9842
10029
|
];
|
|
10030
|
+
var FIRST_CLASS_SLASH_COMMANDS = ["run-plan", "run-plan-all"];
|
|
9843
10031
|
var RUN_PROMOTE_BLOCKED = ["git-prod", "kit-prod"];
|
|
9844
10032
|
function normalizeSlashName(raw) {
|
|
9845
10033
|
return raw.replace(/^\//, "").replace(/\.md$/i, "").trim();
|
|
@@ -9851,8 +10039,26 @@ function classifySlash(name) {
|
|
|
9851
10039
|
if (RUN_CATALOG.includes(n)) return "catalog";
|
|
9852
10040
|
return "unknown";
|
|
9853
10041
|
}
|
|
10042
|
+
function rewriteRootArgvToRun(argv) {
|
|
10043
|
+
const idx = argv.findIndex((arg) => arg.length > 0 && !arg.startsWith("-"));
|
|
10044
|
+
if (idx < 0) return argv;
|
|
10045
|
+
const token = argv[idx];
|
|
10046
|
+
if (!token || token === "run") return argv;
|
|
10047
|
+
const kind = classifySlash(token);
|
|
10048
|
+
if (kind === "unknown") return argv;
|
|
10049
|
+
const slash = normalizeSlashName(token);
|
|
10050
|
+
if (FIRST_CLASS_SLASH_COMMANDS.includes(slash)) {
|
|
10051
|
+
if (token === slash) return argv;
|
|
10052
|
+
const next2 = [...argv];
|
|
10053
|
+
next2[idx] = slash;
|
|
10054
|
+
return next2;
|
|
10055
|
+
}
|
|
10056
|
+
const next = [...argv];
|
|
10057
|
+
next.splice(idx, 1, "run", slash);
|
|
10058
|
+
return next;
|
|
10059
|
+
}
|
|
9854
10060
|
function commandMarkdownPath(root, name) {
|
|
9855
|
-
return
|
|
10061
|
+
return path50.join(root, ".cursor", "commands", `${normalizeSlashName(name)}.md`);
|
|
9856
10062
|
}
|
|
9857
10063
|
function buildDispatchPrompt(commandBody) {
|
|
9858
10064
|
return [
|
|
@@ -9936,20 +10142,20 @@ async function runHeadlessDispatch(opts) {
|
|
|
9936
10142
|
});
|
|
9937
10143
|
}
|
|
9938
10144
|
async function ensureDispatchLogPath(root) {
|
|
9939
|
-
const logDir =
|
|
10145
|
+
const logDir = path50.join(root, ".cursor", "loop-logs");
|
|
9940
10146
|
await mkdir7(logDir, { recursive: true });
|
|
9941
|
-
return
|
|
10147
|
+
return path50.join(logDir, `run-${stamp2()}.log`);
|
|
9942
10148
|
}
|
|
9943
10149
|
|
|
9944
10150
|
// src/commands/run.ts
|
|
9945
10151
|
function displayPath(target, home = homedir4()) {
|
|
9946
|
-
const resolvedHome =
|
|
10152
|
+
const resolvedHome = path51.resolve(home);
|
|
9947
10153
|
if (target === resolvedHome) return "~";
|
|
9948
|
-
const prefix = resolvedHome.endsWith(
|
|
9949
|
-
return target.startsWith(prefix) ? `~${
|
|
10154
|
+
const prefix = resolvedHome.endsWith(path51.sep) ? resolvedHome : `${resolvedHome}${path51.sep}`;
|
|
10155
|
+
return target.startsWith(prefix) ? `~${path51.sep}${target.slice(prefix.length)}` : target;
|
|
9950
10156
|
}
|
|
9951
10157
|
async function executeRun(input) {
|
|
9952
|
-
const root =
|
|
10158
|
+
const root = path51.resolve(input.cwd);
|
|
9953
10159
|
const slash = normalizeSlashName(input.slash);
|
|
9954
10160
|
if (!slash) {
|
|
9955
10161
|
return { exitCode: 1, error: "Provide a slash: agent-kit run <slash>" };
|
|
@@ -9998,7 +10204,7 @@ async function executeRun(input) {
|
|
|
9998
10204
|
const stdout = [
|
|
9999
10205
|
"--dry-run: no agent will be started.",
|
|
10000
10206
|
`Slash: ${slash}`,
|
|
10001
|
-
`Command file: ${
|
|
10207
|
+
`Command file: ${path51.relative(root, file.path)}`,
|
|
10002
10208
|
`Backend: ${detected.id} (${displayPath(detected.bin)})`,
|
|
10003
10209
|
"Prompt:",
|
|
10004
10210
|
prompt
|
|
@@ -10007,8 +10213,8 @@ async function executeRun(input) {
|
|
|
10007
10213
|
}
|
|
10008
10214
|
const logPath = await ensureDispatchLogPath(root);
|
|
10009
10215
|
console.log(`Dispatch: ${slash} via ${detected.id}`);
|
|
10010
|
-
console.log(`Command file: ${
|
|
10011
|
-
console.log(`Log: ${
|
|
10216
|
+
console.log(`Command file: ${path51.relative(root, file.path)}`);
|
|
10217
|
+
console.log(`Log: ${path51.relative(root, logPath)}`);
|
|
10012
10218
|
try {
|
|
10013
10219
|
const result = await runHeadlessDispatch({
|
|
10014
10220
|
backendId: detected.id,
|
|
@@ -10023,6 +10229,68 @@ async function executeRun(input) {
|
|
|
10023
10229
|
return { exitCode: 1, error: String(err) };
|
|
10024
10230
|
}
|
|
10025
10231
|
}
|
|
10232
|
+
var runDispatchArgs = {
|
|
10233
|
+
cwd: {
|
|
10234
|
+
type: "string",
|
|
10235
|
+
description: "Project root (default: current directory)",
|
|
10236
|
+
default: process.cwd()
|
|
10237
|
+
},
|
|
10238
|
+
backend: {
|
|
10239
|
+
type: "string",
|
|
10240
|
+
description: `Agent CLI (${listDetectBackendIds().join(" | ")}; default: auto)`,
|
|
10241
|
+
default: "auto"
|
|
10242
|
+
},
|
|
10243
|
+
model: {
|
|
10244
|
+
type: "string",
|
|
10245
|
+
description: "Optional model id passed to the agent CLI",
|
|
10246
|
+
default: ""
|
|
10247
|
+
},
|
|
10248
|
+
"dry-run": {
|
|
10249
|
+
type: "boolean",
|
|
10250
|
+
description: "Print the resolved backend and prompt, then exit without starting an agent",
|
|
10251
|
+
default: false
|
|
10252
|
+
},
|
|
10253
|
+
"max-ticks": {
|
|
10254
|
+
type: "string",
|
|
10255
|
+
description: "For run-plan alias only: maximum ticks (default: 10)",
|
|
10256
|
+
default: "10"
|
|
10257
|
+
},
|
|
10258
|
+
sleep: {
|
|
10259
|
+
type: "string",
|
|
10260
|
+
description: "For run-plan alias only: seconds between ticks (default: 5)",
|
|
10261
|
+
default: "5"
|
|
10262
|
+
}
|
|
10263
|
+
};
|
|
10264
|
+
async function runSlashCli(slash, args) {
|
|
10265
|
+
const maxTicks = Number.parseInt(String(args["max-ticks"]), 10);
|
|
10266
|
+
const sleepSeconds = Number.parseFloat(String(args.sleep));
|
|
10267
|
+
if (!Number.isFinite(maxTicks) || maxTicks < 1) {
|
|
10268
|
+
logger.error("--max-ticks must be a positive integer");
|
|
10269
|
+
process.exitCode = 1;
|
|
10270
|
+
return;
|
|
10271
|
+
}
|
|
10272
|
+
if (!Number.isFinite(sleepSeconds) || sleepSeconds < 0) {
|
|
10273
|
+
logger.error("--sleep must be a non-negative number");
|
|
10274
|
+
process.exitCode = 1;
|
|
10275
|
+
return;
|
|
10276
|
+
}
|
|
10277
|
+
const result = await executeRun({
|
|
10278
|
+
slash,
|
|
10279
|
+
cwd: String(args.cwd),
|
|
10280
|
+
backend: String(args.backend),
|
|
10281
|
+
model: args.model ? String(args.model) : void 0,
|
|
10282
|
+
dryRun: Boolean(args["dry-run"]),
|
|
10283
|
+
maxTicks,
|
|
10284
|
+
sleepSeconds
|
|
10285
|
+
});
|
|
10286
|
+
if (result.stdout) {
|
|
10287
|
+
console.log(result.stdout);
|
|
10288
|
+
}
|
|
10289
|
+
if (result.error) {
|
|
10290
|
+
logger.error(result.error);
|
|
10291
|
+
}
|
|
10292
|
+
process.exitCode = result.exitCode;
|
|
10293
|
+
}
|
|
10026
10294
|
var runCommand = defineCommand17({
|
|
10027
10295
|
meta: {
|
|
10028
10296
|
name: "run",
|
|
@@ -10031,69 +10299,23 @@ var runCommand = defineCommand17({
|
|
|
10031
10299
|
args: {
|
|
10032
10300
|
slash: {
|
|
10033
10301
|
type: "positional",
|
|
10034
|
-
description: "Slash name (e.g.
|
|
10302
|
+
description: "Slash name (e.g. run-plan-all, backlog-add, continue-plan)",
|
|
10035
10303
|
required: true
|
|
10036
10304
|
},
|
|
10037
|
-
|
|
10038
|
-
type: "string",
|
|
10039
|
-
description: "Project root (default: current directory)",
|
|
10040
|
-
default: process.cwd()
|
|
10041
|
-
},
|
|
10042
|
-
backend: {
|
|
10043
|
-
type: "string",
|
|
10044
|
-
description: `Agent CLI (${listDetectBackendIds().join(" | ")}; default: auto)`,
|
|
10045
|
-
default: "auto"
|
|
10046
|
-
},
|
|
10047
|
-
model: {
|
|
10048
|
-
type: "string",
|
|
10049
|
-
description: "Optional model id passed to the agent CLI",
|
|
10050
|
-
default: ""
|
|
10051
|
-
},
|
|
10052
|
-
"dry-run": {
|
|
10053
|
-
type: "boolean",
|
|
10054
|
-
description: "Print the resolved backend and prompt, then exit without starting an agent",
|
|
10055
|
-
default: false
|
|
10056
|
-
},
|
|
10057
|
-
"max-ticks": {
|
|
10058
|
-
type: "string",
|
|
10059
|
-
description: "For run-plan alias only: maximum ticks (default: 10)",
|
|
10060
|
-
default: "10"
|
|
10061
|
-
},
|
|
10062
|
-
sleep: {
|
|
10063
|
-
type: "string",
|
|
10064
|
-
description: "For run-plan alias only: seconds between ticks (default: 5)",
|
|
10065
|
-
default: "5"
|
|
10066
|
-
}
|
|
10305
|
+
...runDispatchArgs
|
|
10067
10306
|
},
|
|
10068
10307
|
async run({ args }) {
|
|
10069
|
-
|
|
10070
|
-
|
|
10071
|
-
|
|
10072
|
-
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
|
|
10076
|
-
|
|
10077
|
-
|
|
10078
|
-
|
|
10079
|
-
|
|
10080
|
-
}
|
|
10081
|
-
const result = await executeRun({
|
|
10082
|
-
slash: String(args.slash ?? ""),
|
|
10083
|
-
cwd: String(args.cwd),
|
|
10084
|
-
backend: String(args.backend),
|
|
10085
|
-
model: args.model ? String(args.model) : void 0,
|
|
10086
|
-
dryRun: Boolean(args["dry-run"]),
|
|
10087
|
-
maxTicks,
|
|
10088
|
-
sleepSeconds
|
|
10089
|
-
});
|
|
10090
|
-
if (result.stdout) {
|
|
10091
|
-
console.log(result.stdout);
|
|
10092
|
-
}
|
|
10093
|
-
if (result.error) {
|
|
10094
|
-
logger.error(result.error);
|
|
10095
|
-
}
|
|
10096
|
-
process.exitCode = result.exitCode;
|
|
10308
|
+
await runSlashCli(String(args.slash ?? ""), args);
|
|
10309
|
+
}
|
|
10310
|
+
});
|
|
10311
|
+
var runPlanAllCommand = defineCommand17({
|
|
10312
|
+
meta: {
|
|
10313
|
+
name: "run-plan-all",
|
|
10314
|
+
description: "Headless /run-plan-all queue from the L0 file. Numbered-list HITL. Never git-prod."
|
|
10315
|
+
},
|
|
10316
|
+
args: runDispatchArgs,
|
|
10317
|
+
async run({ args }) {
|
|
10318
|
+
await runSlashCli("run-plan-all", args);
|
|
10097
10319
|
}
|
|
10098
10320
|
});
|
|
10099
10321
|
|
|
@@ -10120,22 +10342,21 @@ var scanCommand = defineCommand18({
|
|
|
10120
10342
|
});
|
|
10121
10343
|
|
|
10122
10344
|
// src/commands/setup-global.ts
|
|
10123
|
-
import { spawn as
|
|
10345
|
+
import { spawn as spawn9 } from "child_process";
|
|
10124
10346
|
import { appendFile, mkdir as mkdir8, readFile as readFile26, writeFile as writeFile13 } from "fs/promises";
|
|
10125
10347
|
import { homedir as homedir5 } from "os";
|
|
10126
|
-
import
|
|
10348
|
+
import path52 from "path";
|
|
10127
10349
|
import { confirm as confirm2, isCancel as isCancel2 } from "@clack/prompts";
|
|
10128
10350
|
import { defineCommand as defineCommand19 } from "citty";
|
|
10129
10351
|
import { cyan as cyan5, green as green4, yellow as yellow3 } from "kolorist";
|
|
10130
10352
|
var NPM_GLOBAL_DIR_NAME = ".npm-global";
|
|
10131
10353
|
var SETUP_GLOBAL_MARKER = "# agent-kit setup-global";
|
|
10132
|
-
var DEFAULT_PACKAGE_SPEC = "@dadado/agent-kit-cli";
|
|
10133
10354
|
function planSetupGlobalSteps(env, options = {}) {
|
|
10134
10355
|
const homeDir = options.homeDir ?? homedir5();
|
|
10135
|
-
const packageSpec = options.packageSpec ??
|
|
10136
|
-
const npmGlobalDir =
|
|
10137
|
-
const npmGlobalBin =
|
|
10138
|
-
const npmrcPath =
|
|
10356
|
+
const packageSpec = options.packageSpec ?? pinnedCliSpec();
|
|
10357
|
+
const npmGlobalDir = path52.join(homeDir, NPM_GLOBAL_DIR_NAME);
|
|
10358
|
+
const npmGlobalBin = path52.join(npmGlobalDir, "bin");
|
|
10359
|
+
const npmrcPath = path52.join(homeDir, ".npmrc");
|
|
10139
10360
|
const npmrcPrefixValue = `~/${NPM_GLOBAL_DIR_NAME}`;
|
|
10140
10361
|
const pathExportLine = `export PATH="${npmGlobalBin}:$PATH"`;
|
|
10141
10362
|
const shellProfile = env.shellProfile;
|
|
@@ -10215,7 +10436,7 @@ async function safeReadFile(fs, filePath) {
|
|
|
10215
10436
|
}
|
|
10216
10437
|
}
|
|
10217
10438
|
var defaultNpmInstallImpl = (packageSpec) => new Promise((resolve3) => {
|
|
10218
|
-
const child =
|
|
10439
|
+
const child = spawn9("npm", ["i", "-g", packageSpec], { stdio: "inherit" });
|
|
10219
10440
|
child.on("error", (error) => resolve3({ ok: false, error }));
|
|
10220
10441
|
child.on("close", (code) => {
|
|
10221
10442
|
if (code === 0) resolve3({ ok: true });
|
|
@@ -10266,11 +10487,48 @@ async function runSetupGlobal(options = {}) {
|
|
|
10266
10487
|
const homeDir = options.homeDir ?? homedir5();
|
|
10267
10488
|
const env = await assessEnvironmentImpl(options);
|
|
10268
10489
|
const plan = planSetupGlobalSteps(env, { homeDir, packageSpec: options.packageSpec });
|
|
10269
|
-
if (plan.alreadyWritable) {
|
|
10490
|
+
if (plan.alreadyWritable && pathCliStatus(env, KIT_VERSION) === "current") {
|
|
10270
10491
|
printHeader(env, print);
|
|
10271
|
-
print(green4("npm's global prefix is
|
|
10492
|
+
print(green4("npm's global prefix is writable and PATH `agent-kit` matches this CLI."));
|
|
10272
10493
|
return { exitCode: 0, mutated: false, outcome: "already-ok", env, plan };
|
|
10273
10494
|
}
|
|
10495
|
+
if (plan.alreadyWritable) {
|
|
10496
|
+
printHeader(env, print);
|
|
10497
|
+
print(
|
|
10498
|
+
`PATH \`agent-kit\` is ${env.binVersion ? `v${env.binVersion}` : "missing or unreadable"}; this CLI is v${KIT_VERSION}.`
|
|
10499
|
+
);
|
|
10500
|
+
print(`Prefix is writable. Next step is only: npm i -g ${plan.packageSpec}`);
|
|
10501
|
+
if (options.dryRun) {
|
|
10502
|
+
print("Dry run: no changes.");
|
|
10503
|
+
print(` npm i -g ${plan.packageSpec}`);
|
|
10504
|
+
return { exitCode: 0, mutated: false, outcome: "dry-run", env, plan };
|
|
10505
|
+
}
|
|
10506
|
+
const nonInteractiveWritable = options.nonInteractive ?? isNonInteractive();
|
|
10507
|
+
if (nonInteractiveWritable) {
|
|
10508
|
+
print("No changes made. Run this yourself:");
|
|
10509
|
+
print(` npm i -g ${plan.packageSpec}`);
|
|
10510
|
+
print(" hash -r");
|
|
10511
|
+
print(" agent-kit --version");
|
|
10512
|
+
return { exitCode: 0, mutated: false, outcome: "manual-instructions", env, plan };
|
|
10513
|
+
}
|
|
10514
|
+
const confirmStep2 = options.confirmImpl ?? defaultConfirmImpl;
|
|
10515
|
+
const npmInstall2 = options.npmInstallImpl ?? defaultNpmInstallImpl;
|
|
10516
|
+
const proceedInstall2 = await confirmStep2(`Run: npm i -g ${plan.packageSpec}?`);
|
|
10517
|
+
if (!proceedInstall2) {
|
|
10518
|
+
print(yellow3("Cancelled: no changes made."));
|
|
10519
|
+
return { exitCode: 1, mutated: false, outcome: "cancelled", env, plan };
|
|
10520
|
+
}
|
|
10521
|
+
const installResult2 = await npmInstall2(plan.packageSpec);
|
|
10522
|
+
if (!installResult2.ok) {
|
|
10523
|
+
const hint = classifyInstallError(installResult2.error);
|
|
10524
|
+
print(` npm install failed: ${hint.message}`);
|
|
10525
|
+
print(hint.recovery);
|
|
10526
|
+
return { exitCode: 1, mutated: false, outcome: "error", env, plan };
|
|
10527
|
+
}
|
|
10528
|
+
print(green4(` done: ${plan.packageSpec} installed globally.`));
|
|
10529
|
+
print(" If this shell still shows the old version: hash -r (or open a new terminal).");
|
|
10530
|
+
return { exitCode: 0, mutated: true, outcome: "completed", env, plan };
|
|
10531
|
+
}
|
|
10274
10532
|
if (options.dryRun) {
|
|
10275
10533
|
printHeader(env, print);
|
|
10276
10534
|
print("Dry run \u2014 no changes will be made. Steps that would run:");
|
|
@@ -10397,7 +10655,7 @@ var setupGlobalCommand = defineCommand19({
|
|
|
10397
10655
|
});
|
|
10398
10656
|
|
|
10399
10657
|
// src/commands/status.ts
|
|
10400
|
-
import
|
|
10658
|
+
import path53 from "path";
|
|
10401
10659
|
import { defineCommand as defineCommand20 } from "citty";
|
|
10402
10660
|
function profileStatus(profile) {
|
|
10403
10661
|
if (!profile) return { origin: "none", evidence: [], profile: null };
|
|
@@ -10428,13 +10686,14 @@ var statusCommand = defineCommand20({
|
|
|
10428
10686
|
}
|
|
10429
10687
|
},
|
|
10430
10688
|
async run({ args }) {
|
|
10431
|
-
const rootDir =
|
|
10432
|
-
const [manifest, rawProfile, scan] = await Promise.all([
|
|
10689
|
+
const rootDir = path53.resolve(args.cwd);
|
|
10690
|
+
const [manifest, rawProfile, scan, env] = await Promise.all([
|
|
10433
10691
|
loadAgentKitManifest(rootDir),
|
|
10434
10692
|
readJson(
|
|
10435
|
-
|
|
10693
|
+
path53.join(rootDir, ".cursor", "agent-kit.config.json")
|
|
10436
10694
|
),
|
|
10437
|
-
runScanner(rootDir)
|
|
10695
|
+
runScanner(rootDir),
|
|
10696
|
+
assessEnvironment()
|
|
10438
10697
|
]);
|
|
10439
10698
|
const readiness = createReadinessReport(scan, { generatorVersion: KIT_VERSION });
|
|
10440
10699
|
const profile = profileStatus(rawProfile);
|
|
@@ -10470,6 +10729,17 @@ var statusCommand = defineCommand20({
|
|
|
10470
10729
|
` registry: ${manifest.registry?.url ?? "(default)"} @ ${manifest.registry?.ref ?? "(default)"}`
|
|
10471
10730
|
);
|
|
10472
10731
|
if (manifest.installedAt) console.log(` installed at: ${manifest.installedAt}`);
|
|
10732
|
+
if (manifest.version !== KIT_VERSION) {
|
|
10733
|
+
console.log(
|
|
10734
|
+
` overlay: this CLI is v${KIT_VERSION}; apply with the same binary, not a stale PATH hit:`
|
|
10735
|
+
);
|
|
10736
|
+
console.log(` ${npxPinned(KIT_VERSION, "update")}`);
|
|
10737
|
+
}
|
|
10738
|
+
const pathStatus = pathCliStatus(env, KIT_VERSION);
|
|
10739
|
+
if (pathStatus === "behind" || pathStatus === "unknown") {
|
|
10740
|
+
console.log(` PATH bin: v${env.binVersion ?? "unknown"} at ${env.binPath}`);
|
|
10741
|
+
console.log(" bare `agent-kit update` will re-stamp that older version");
|
|
10742
|
+
}
|
|
10473
10743
|
}
|
|
10474
10744
|
console.log("Repository readiness");
|
|
10475
10745
|
console.log(
|
|
@@ -10656,6 +10926,8 @@ ${err.recovery}
|
|
|
10656
10926
|
logApplyStats(stats);
|
|
10657
10927
|
const transition = next.version === existing.version ? `unchanged at v${next.version}` : `v${existing.version} \u2192 v${next.version}`;
|
|
10658
10928
|
logger.success(`Update complete: ${transition} (L3 protected paths left untouched).`);
|
|
10929
|
+
const sync = await syncPathCliToRuntime({ runtimeVersion: KIT_VERSION });
|
|
10930
|
+
for (const line of sync.lines) console.log(line);
|
|
10659
10931
|
} finally {
|
|
10660
10932
|
await registry.unlock?.();
|
|
10661
10933
|
}
|
|
@@ -10664,7 +10936,7 @@ ${err.recovery}
|
|
|
10664
10936
|
|
|
10665
10937
|
// src/commands/validate.ts
|
|
10666
10938
|
import { readFile as readFile27 } from "fs/promises";
|
|
10667
|
-
import
|
|
10939
|
+
import path54 from "path";
|
|
10668
10940
|
import { defineCommand as defineCommand22 } from "citty";
|
|
10669
10941
|
|
|
10670
10942
|
// src/invariants/plan-schema.ts
|
|
@@ -10711,7 +10983,7 @@ function validatePlanFrontmatterText(text) {
|
|
|
10711
10983
|
// src/commands/validate.ts
|
|
10712
10984
|
async function resolveEditedPath(cwd, explicit) {
|
|
10713
10985
|
if (explicit) {
|
|
10714
|
-
const filePath2 =
|
|
10986
|
+
const filePath2 = path54.resolve(cwd, explicit);
|
|
10715
10987
|
try {
|
|
10716
10988
|
return { filePath: filePath2, content: await readFile27(filePath2, "utf8") };
|
|
10717
10989
|
} catch {
|
|
@@ -10721,7 +10993,7 @@ async function resolveEditedPath(cwd, explicit) {
|
|
|
10721
10993
|
const payload = await readStdinJson();
|
|
10722
10994
|
const rel = typeof payload.file_path === "string" && payload.file_path || typeof payload.path === "string" && payload.path || typeof payload.file === "string" && payload.file || "";
|
|
10723
10995
|
if (!rel) return null;
|
|
10724
|
-
const filePath =
|
|
10996
|
+
const filePath = path54.isAbsolute(rel) ? rel : path54.resolve(cwd, rel);
|
|
10725
10997
|
try {
|
|
10726
10998
|
return { filePath, content: await readFile27(filePath, "utf8") };
|
|
10727
10999
|
} catch {
|
|
@@ -10751,7 +11023,7 @@ var validateCommand = defineCommand22({
|
|
|
10751
11023
|
async run({ args }) {
|
|
10752
11024
|
const cwd = typeof args.cwd === "string" ? args.cwd : process.cwd();
|
|
10753
11025
|
const fileArg = typeof args.file === "string" ? args.file : void 0;
|
|
10754
|
-
const filePath = fileArg ?
|
|
11026
|
+
const filePath = fileArg ? path54.resolve(cwd, fileArg) : path54.join(path54.resolve(cwd), ".cursor", "HANDOFF.md");
|
|
10755
11027
|
let content = "";
|
|
10756
11028
|
try {
|
|
10757
11029
|
content = await readFile27(filePath, "utf8");
|
|
@@ -10778,7 +11050,7 @@ var validateCommand = defineCommand22({
|
|
|
10778
11050
|
process.exitCode = 2;
|
|
10779
11051
|
return;
|
|
10780
11052
|
}
|
|
10781
|
-
const filePath =
|
|
11053
|
+
const filePath = path54.resolve(cwd, fileArg);
|
|
10782
11054
|
let content = "";
|
|
10783
11055
|
try {
|
|
10784
11056
|
content = await readFile27(filePath, "utf8");
|
|
@@ -10800,7 +11072,7 @@ var validateCommand = defineCommand22({
|
|
|
10800
11072
|
},
|
|
10801
11073
|
async run({ args }) {
|
|
10802
11074
|
const cwd = typeof args.cwd === "string" ? args.cwd : process.cwd();
|
|
10803
|
-
const resolved = await resolveEditedPath(
|
|
11075
|
+
const resolved = await resolveEditedPath(path54.resolve(cwd));
|
|
10804
11076
|
if (!resolved) {
|
|
10805
11077
|
console.log(JSON.stringify({}));
|
|
10806
11078
|
return;
|
|
@@ -10913,7 +11185,7 @@ function renderWelcomeScreen(opts = {}) {
|
|
|
10913
11185
|
})(),
|
|
10914
11186
|
"",
|
|
10915
11187
|
muted2(
|
|
10916
|
-
"
|
|
11188
|
+
"Terminal: agent-kit run-plan-all (same as agent-kit run run-plan-all). Cursor chat: /run-plan-all."
|
|
10917
11189
|
),
|
|
10918
11190
|
muted2(
|
|
10919
11191
|
`${shouldUseVisualMotion(opts) ? SPACE_MARKS.star : SPACE_MARKS.tick} ${tipAt(
|
|
@@ -10938,7 +11210,7 @@ var CLI_HELP_GROUPS = [
|
|
|
10938
11210
|
{
|
|
10939
11211
|
id: "mission",
|
|
10940
11212
|
title: "MISSION",
|
|
10941
|
-
commands: ["handoff", "plan-index", "run", "run-plan"]
|
|
11213
|
+
commands: ["handoff", "plan-index", "run", "run-plan", "run-plan-all"]
|
|
10942
11214
|
},
|
|
10943
11215
|
{
|
|
10944
11216
|
id: "dashboard",
|
|
@@ -11004,7 +11276,7 @@ async function renderGroupedRootHelp(cmd) {
|
|
|
11004
11276
|
lines.push(
|
|
11005
11277
|
g(`Use \`${name} <command> --help\` for more information about a command.`),
|
|
11006
11278
|
g(
|
|
11007
|
-
"Ask questions is Cursor-only. Use `agent-kit run <slash>` for headless numbered-list HITL. `/git-prod` stays operator-gated."
|
|
11279
|
+
"Ask questions is Cursor-only. Use `agent-kit run-plan-all` or `agent-kit run <slash>` for headless numbered-list HITL. `/git-prod` stays operator-gated."
|
|
11008
11280
|
),
|
|
11009
11281
|
g(`${tipMark} ${tip}`),
|
|
11010
11282
|
""
|
|
@@ -11013,6 +11285,9 @@ async function renderGroupedRootHelp(cmd) {
|
|
|
11013
11285
|
}
|
|
11014
11286
|
|
|
11015
11287
|
// src/index.ts
|
|
11288
|
+
var rewrittenArgv = rewriteRootArgvToRun(process.argv.slice(2));
|
|
11289
|
+
process.argv.length = 2;
|
|
11290
|
+
process.argv.push(...rewrittenArgv);
|
|
11016
11291
|
var main = defineCommand23({
|
|
11017
11292
|
meta: {
|
|
11018
11293
|
name: "agent-kit",
|
|
@@ -11035,6 +11310,7 @@ var main = defineCommand23({
|
|
|
11035
11310
|
"plan-index": planIndexCommand,
|
|
11036
11311
|
run: runCommand,
|
|
11037
11312
|
"run-plan": runPlanCommand,
|
|
11313
|
+
"run-plan-all": runPlanAllCommand,
|
|
11038
11314
|
dashboard: dashboardCommand,
|
|
11039
11315
|
"dashboard-broadcast": dashboardBroadcastCommand,
|
|
11040
11316
|
"mission-control": missionControlCommand,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dadado/agent-kit-cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.9.0",
|
|
4
4
|
"description": "Agent Kit CLI: HITL framework install and tooling for AI-assisted IDEs (rules, skills, plan/handoff, context).",
|
|
5
5
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
6
6
|
"type": "module",
|