@dadado/agent-kit-cli 5.15.0 → 5.16.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.
Files changed (71) hide show
  1. package/dashboard/dashboard-data.mjs +69 -65
  2. package/dashboard/lib/guards.d.mts +5 -0
  3. package/dashboard/lib/guards.mjs +31 -0
  4. package/dashboard/lib/identity-probe.mjs +56 -0
  5. package/dashboard/lib/pipeline-cache.mjs +58 -0
  6. package/dashboard/lib/processes.mjs +71 -0
  7. package/dashboard/serve.mjs +43 -1
  8. package/dashboard/start-broadcast.mjs +2 -12
  9. package/dashboard/start.mjs +2 -13
  10. package/dist/add-7UMSGVWC.js +150 -0
  11. package/dist/chunk-2IPXQFJE.js +253 -0
  12. package/dist/chunk-2YU2H7I6.js +42 -0
  13. package/dist/chunk-4IWG5CVE.js +214 -0
  14. package/dist/chunk-5OXPNVCF.js +106 -0
  15. package/dist/chunk-5VCOWTTP.js +6 -0
  16. package/dist/chunk-6QV2BFGA.js +341 -0
  17. package/dist/chunk-77V75A7O.js +39 -0
  18. package/dist/chunk-7HDQEK6T.js +26 -0
  19. package/dist/chunk-CBCW5R5J.js +484 -0
  20. package/dist/chunk-CGTE7DHN.js +410 -0
  21. package/dist/chunk-DE3LQFSJ.js +18 -0
  22. package/dist/chunk-F6C3GFKV.js +57 -0
  23. package/dist/chunk-HFUH3HVS.js +282 -0
  24. package/dist/chunk-HS7LVVLO.js +74 -0
  25. package/dist/chunk-IHROBTNM.js +135 -0
  26. package/dist/chunk-KD2MYBB6.js +213 -0
  27. package/dist/chunk-KI6ZHBPV.js +332 -0
  28. package/dist/chunk-MAPOQEA2.js +43 -0
  29. package/dist/chunk-NQ7IQ5XT.js +26 -0
  30. package/dist/chunk-OUQZC744.js +1315 -0
  31. package/dist/chunk-OZ4QV6LM.js +1078 -0
  32. package/dist/chunk-PCCQUWE5.js +817 -0
  33. package/dist/chunk-PNFF6OU3.js +273 -0
  34. package/dist/chunk-QTON2GQX.js +203 -0
  35. package/dist/chunk-TFZ2JUXH.js +1081 -0
  36. package/dist/chunk-VGZBARQC.js +318 -0
  37. package/dist/chunk-VS2JD2XC.js +1453 -0
  38. package/dist/chunk-VY7MTPJ2.js +205 -0
  39. package/dist/chunk-WW3YZKHW.js +165 -0
  40. package/dist/chunk-XWPO3VYQ.js +53 -0
  41. package/dist/chunk-XZZAVHH4.js +503 -0
  42. package/dist/chunk-YGBBHKBE.js +82 -0
  43. package/dist/chunk-ZB43YMHW.js +20 -0
  44. package/dist/chunk-ZCTSUQRR.js +874 -0
  45. package/dist/chunk-ZXKZBTXE.js +17 -0
  46. package/dist/contribute-YKK6YCSI.js +367 -0
  47. package/dist/cursor-awareness-KTL2RGKD.js +77 -0
  48. package/dist/dashboard-YSNUGBFY.js +21 -0
  49. package/dist/dashboard-broadcast-M4CMW7RX.js +119 -0
  50. package/dist/diff-YTR7VOAN.js +74 -0
  51. package/dist/doctor-TA2FWREU.js +497 -0
  52. package/dist/dogfood-KKFVRWT6.js +366 -0
  53. package/dist/guard-EHXF76ID.js +530 -0
  54. package/dist/handoff-3UI6VKVG.js +302 -0
  55. package/dist/hook-MUV6Y7UW.js +1074 -0
  56. package/dist/index.js +62 -14068
  57. package/dist/init-TTTKGC4C.js +127 -0
  58. package/dist/install-ZMFJBPOI.js +34 -0
  59. package/dist/mission-control-LJACEVVN.js +89 -0
  60. package/dist/monitors-QV2IS3MP.js +176 -0
  61. package/dist/plan-index-JMC7Z4DW.js +44 -0
  62. package/dist/public-inbound-radar-WP3XF7GS.js +68 -0
  63. package/dist/remote-issues-SZ4HDQL5.js +44 -0
  64. package/dist/run-I3BFGULT.js +243 -0
  65. package/dist/run-plan-FO7CL4M3.js +118 -0
  66. package/dist/scan-NI2SWJ2E.js +33 -0
  67. package/dist/setup-global-JUVMJXJ5.js +340 -0
  68. package/dist/status-MVCUNCWX.js +138 -0
  69. package/dist/update-Q4EBIRUB.js +260 -0
  70. package/dist/validate-V2CW7J4B.js +201 -0
  71. package/package.json +1 -1
@@ -0,0 +1,318 @@
1
+ import {
2
+ assessEnvironment
3
+ } from "./chunk-4IWG5CVE.js";
4
+ import {
5
+ compareSemver,
6
+ normalizeSemver
7
+ } from "./chunk-XZZAVHH4.js";
8
+ import {
9
+ MANIFEST_RELATIVE_PATH
10
+ } from "./chunk-VS2JD2XC.js";
11
+ import {
12
+ KIT_VERSION,
13
+ pinnedCliSpec
14
+ } from "./chunk-7HDQEK6T.js";
15
+ import {
16
+ fileExists
17
+ } from "./chunk-77V75A7O.js";
18
+
19
+ // src/utils/terminal.ts
20
+ import { readdir } from "fs/promises";
21
+ import { homedir } from "os";
22
+ import path from "path";
23
+ import { confirm, isCancel } from "@clack/prompts";
24
+ function isNonInteractive() {
25
+ if (process.env.CI === "true" || process.env.CI === "1") return true;
26
+ if (process.env.AGENT_KIT_YES === "1") return true;
27
+ return !process.stdin.isTTY;
28
+ }
29
+ var NESTED_REPO_AMBIGUITY_THRESHOLD = 2;
30
+ var NESTED_REPO_SCAN_LIMIT = 200;
31
+ async function findNestedRepoChildren(resolved) {
32
+ let entries;
33
+ try {
34
+ entries = await readdir(resolved, { withFileTypes: true });
35
+ } catch {
36
+ return [];
37
+ }
38
+ const nested = [];
39
+ let scanned = 0;
40
+ for (const entry of entries) {
41
+ if (nested.length >= NESTED_REPO_AMBIGUITY_THRESHOLD) break;
42
+ if (scanned >= NESTED_REPO_SCAN_LIMIT) break;
43
+ if (!entry.isDirectory()) continue;
44
+ if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
45
+ scanned += 1;
46
+ if (await fileExists(path.join(resolved, entry.name, ".git"))) {
47
+ nested.push(entry.name);
48
+ }
49
+ }
50
+ return nested;
51
+ }
52
+ async function validateProjectRoot(resolved) {
53
+ const home = path.resolve(homedir());
54
+ if (resolved === "/" || resolved === home) {
55
+ return {
56
+ ok: false,
57
+ reason: `Refused to use ${resolved} as a project root.`,
58
+ recovery: "Change into a project directory and re-run. Agent Kit installs per project."
59
+ };
60
+ }
61
+ const hasGit = await fileExists(path.join(resolved, ".git"));
62
+ const hasManifest = await fileExists(path.join(resolved, MANIFEST_RELATIVE_PATH));
63
+ if (!hasGit && !hasManifest) {
64
+ return {
65
+ ok: false,
66
+ reason: `Refused ${resolved}: no .git and no ${MANIFEST_RELATIVE_PATH}.`,
67
+ recovery: [
68
+ "Starting from an empty folder? Pick one of these:",
69
+ " 1. git init - then re-run. Recommended: readiness and the",
70
+ " staging -> prod flow both want Git.",
71
+ " 2. --force-root - install without Git. /agent-kit-onboard will",
72
+ " still offer to initialize it later.",
73
+ " 3. Answer yes to the 'Proceed anyway?' prompt in an interactive terminal.",
74
+ "Or re-run from the project directory you actually meant."
75
+ ].join("\n")
76
+ };
77
+ }
78
+ if (hasGit && !hasManifest) {
79
+ const nested = await findNestedRepoChildren(resolved);
80
+ if (nested.length >= NESTED_REPO_AMBIGUITY_THRESHOLD) {
81
+ return {
82
+ ok: false,
83
+ reason: `Refused ${resolved}: it has .git but also contains child repositories (${nested.join(", ")}). This looks like a parent-of-repos folder, not a project root.`,
84
+ recovery: [
85
+ "L0 belongs in one project, not in the folder that holds several.",
86
+ " 1. cd into the project you meant, then re-run.",
87
+ " 2. --force-root - only if this parent folder really is the project root."
88
+ ].join("\n")
89
+ };
90
+ }
91
+ }
92
+ return { ok: true };
93
+ }
94
+ async function confirmProjectRoot(cwd, opts) {
95
+ const resolved = path.resolve(cwd);
96
+ if (opts.forceRoot) {
97
+ return resolved;
98
+ }
99
+ const validation = await validateProjectRoot(resolved);
100
+ if (!validation.ok) {
101
+ if (opts.nonInteractive) {
102
+ throw new RootRefusedError(resolved, validation.reason, validation.recovery);
103
+ }
104
+ const ok2 = await confirm({
105
+ message: `${validation.reason} Proceed anyway?`,
106
+ initialValue: false
107
+ });
108
+ if (isCancel(ok2) || !ok2) {
109
+ throw new RootRefusedError(resolved, validation.reason, validation.recovery);
110
+ }
111
+ return resolved;
112
+ }
113
+ if (opts.nonInteractive) {
114
+ return resolved;
115
+ }
116
+ const ok = await confirm({
117
+ message: `${opts.command === "install" ? "Install" : "Update"} Agent Kit in: ${resolved}`,
118
+ initialValue: true
119
+ });
120
+ if (isCancel(ok) || !ok) {
121
+ throw new RootRefusedError(resolved);
122
+ }
123
+ return resolved;
124
+ }
125
+ var RootRefusedError = class extends Error {
126
+ constructor(root, reason, recovery) {
127
+ super(reason ?? `Refused to write into ${root}. Re-run from the correct project directory.`);
128
+ this.root = root;
129
+ this.recovery = recovery;
130
+ this.name = "RootRefusedError";
131
+ }
132
+ root;
133
+ recovery;
134
+ };
135
+ var NPM_GLOBAL_PREFIX_PATH_RE = /\/lib\/node_modules|Program Files\\nodejs\\node_modules/;
136
+ var NPM_GLOBAL_NODE_MODULES_RE = /node_modules/;
137
+ function isNpmGlobalPrefixError(msg, code) {
138
+ const isPermissionError = code === "EPERM" || code === "EACCES" || /EPERM|EACCES/.test(msg);
139
+ if (!isPermissionError) return false;
140
+ return NPM_GLOBAL_PREFIX_PATH_RE.test(msg) || NPM_GLOBAL_NODE_MODULES_RE.test(msg);
141
+ }
142
+ function classifyInstallError(err) {
143
+ const msg = err instanceof Error ? err.message : String(err);
144
+ const code = err?.code;
145
+ if (isNpmGlobalPrefixError(msg, code)) {
146
+ return {
147
+ kind: "npm-global-eacces",
148
+ message: `Permission error (root-owned npm prefix): ${msg}`,
149
+ recovery: [
150
+ "npm's global install prefix (e.g. /usr/local/lib/node_modules) is owned by root, so global installs fail.",
151
+ "Recovery options:",
152
+ " 1. Run: npx @dadado/agent-kit-cli@latest setup-global (relocates npm's prefix to a folder you own, fixes PATH, reinstalls)",
153
+ ' 2. Manual fix: mkdir -p ~/.npm-global && npm config set prefix "~/.npm-global" && export PATH="~/.npm-global/bin:$PATH" (add to your shell profile) && npm i -g @dadado/agent-kit-cli@latest',
154
+ " 3. Use Port B fallback: drag install.md into the Cursor chat"
155
+ ].join("\n")
156
+ };
157
+ }
158
+ if (code === "EPERM" || code === "EACCES" || /EPERM|EACCES/.test(msg)) {
159
+ return {
160
+ kind: "eperm",
161
+ message: `Permission error: ${msg}`,
162
+ recovery: [
163
+ "The npm cache may have ownership drift (root-written files in a user dir).",
164
+ "Recovery options:",
165
+ " 1. npx --cache .npm-cache @dadado/agent-kit-cli@latest install",
166
+ " 2. npm cache clean --force && npx @dadado/agent-kit-cli@latest install",
167
+ " 3. Use Port B fallback: drag install.md into the Cursor chat"
168
+ ].join("\n")
169
+ };
170
+ }
171
+ if (/403|Forbidden|unauthorized|E401|ENEEDAUTH/.test(msg)) {
172
+ return {
173
+ kind: "registry-auth",
174
+ message: `Registry access denied: ${msg}`,
175
+ recovery: [
176
+ "The npm registry returned 403/401 for the scoped package.",
177
+ "Recovery options:",
178
+ " 1. Check npm auth: npm whoami (login if needed: npm login)",
179
+ " 2. If using a private registry, verify .npmrc scope config",
180
+ " 3. Use Port B fallback: drag install.md into the Cursor chat"
181
+ ].join("\n")
182
+ };
183
+ }
184
+ if (/ENOTFOUND|ETIMEDOUT|ECONNREFUSED|ECONNRESET|EAI_AGAIN|fetch failed/.test(msg) || code === "ENOTFOUND" || code === "ETIMEDOUT") {
185
+ return {
186
+ kind: "network",
187
+ message: `Network error: ${msg}`,
188
+ recovery: [
189
+ "Could not reach the registry or git remote.",
190
+ "Recovery options:",
191
+ " 1. Check network/proxy/VPN settings",
192
+ " 2. Retry: npx @dadado/agent-kit-cli@latest install",
193
+ " 3. Use --registry <local-path> if you have a local checkout"
194
+ ].join("\n")
195
+ };
196
+ }
197
+ return {
198
+ kind: "unknown",
199
+ message: msg,
200
+ recovery: "Unexpected error. Check the message above and retry, or use Port B fallback."
201
+ };
202
+ }
203
+
204
+ // src/lifecycle/path-cli.ts
205
+ import { spawn } from "child_process";
206
+ import path2 from "path";
207
+ function npxPinned(runtimeVersion, subcommand) {
208
+ return `npx -y ${pinnedCliSpec(runtimeVersion)} ${subcommand}`;
209
+ }
210
+ function isBinUnderPrefix(binPath, prefix) {
211
+ const bin = path2.resolve(binPath);
212
+ const root = path2.resolve(prefix);
213
+ return bin === root || bin.startsWith(`${root}${path2.sep}`);
214
+ }
215
+ function pathCliStatus(env, runtimeVersion) {
216
+ if (!env.binOnPath || !env.binPath) return "missing";
217
+ const running = normalizeSemver(runtimeVersion);
218
+ const pathVer = env.binVersion ? normalizeSemver(env.binVersion) : null;
219
+ if (!pathVer || !running) return "unknown";
220
+ try {
221
+ return compareSemver(pathVer, running) >= 0 ? "current" : "behind";
222
+ } catch {
223
+ return "unknown";
224
+ }
225
+ }
226
+ function driftLines(env, runtimeVersion) {
227
+ const pathVer = env.binVersion ?? "unknown";
228
+ const where = env.binPath ?? "(unresolved)";
229
+ return [
230
+ `This CLI is v${runtimeVersion}. PATH \`agent-kit\` is v${pathVer} at:`,
231
+ ` ${where}`,
232
+ "Do not run bare `agent-kit update` or `init` from that binary. It re-stamps the old version.",
233
+ "Keep using the pinned npx form until PATH matches:",
234
+ ` ${npxPinned(runtimeVersion, "update")}`,
235
+ ` ${npxPinned(runtimeVersion, "status")}`
236
+ ];
237
+ }
238
+ function isShadow(env) {
239
+ if (!env.binPath || !env.npmPrefix.prefix) return false;
240
+ return !isBinUnderPrefix(env.binPath, env.npmPrefix.prefix);
241
+ }
242
+ async function spawnNpmGlobalInstall(spec) {
243
+ return new Promise((resolve) => {
244
+ const child = spawn("npm", ["i", "-g", spec], { stdio: "inherit" });
245
+ child.on("error", (error) => resolve({ ok: false, error }));
246
+ child.on("close", (code) => {
247
+ if (code === 0) resolve({ ok: true });
248
+ else resolve({ ok: false, error: new Error(`npm exited with code ${code ?? "unknown"}`) });
249
+ });
250
+ });
251
+ }
252
+ async function syncPathCliToRuntime(options = {}) {
253
+ const runtimeVersion = options.runtimeVersion ?? KIT_VERSION;
254
+ const assess = options.assessEnvironmentImpl ?? assessEnvironment;
255
+ let env = options.env ?? await assess();
256
+ const autoInstall = options.autoInstall ?? !isNonInteractive();
257
+ const lines = [];
258
+ let status = pathCliStatus(env, runtimeVersion);
259
+ if (status === "current") {
260
+ return { status, env, upgraded: false, lines };
261
+ }
262
+ if (status === "behind" || status === "unknown") {
263
+ lines.push(...driftLines(env, runtimeVersion));
264
+ if (isShadow(env)) {
265
+ lines.push(
266
+ "That PATH hit is not npm's global bin, so `npm i -g` may not replace it.",
267
+ "Run `hash -r` and `which -a agent-kit`. Put npm's global bin first, or remove the stale shim."
268
+ );
269
+ }
270
+ }
271
+ if (!autoInstall) {
272
+ return { status, env, upgraded: false, lines };
273
+ }
274
+ if (status === "missing") {
275
+ lines.push("No bare `agent-kit` on PATH yet (npx is ephemeral).");
276
+ }
277
+ if (!env.npmPrefixWritable) {
278
+ lines.push(
279
+ "npm's global prefix is not writable, so this process cannot upgrade PATH.",
280
+ `Run ${npxPinned(runtimeVersion, "setup-global")} (or fix prefix permissions).`
281
+ );
282
+ return { status, env, upgraded: false, lines };
283
+ }
284
+ const spec = pinnedCliSpec(runtimeVersion);
285
+ const install = options.npmInstallImpl ?? spawnNpmGlobalInstall;
286
+ lines.push(`Installing ${spec} into the writable npm prefix...`);
287
+ const outcome = await install(spec);
288
+ if (!outcome.ok) {
289
+ const detail = outcome.error instanceof Error ? outcome.error.message : "npm i -g failed";
290
+ lines.push(`Global install failed: ${detail}`);
291
+ return { status, env, upgraded: false, lines };
292
+ }
293
+ env = await assess();
294
+ status = pathCliStatus(env, runtimeVersion);
295
+ if (status === "current") {
296
+ lines.push(
297
+ `PATH \`agent-kit\` is now v${env.binVersion ?? runtimeVersion}.`,
298
+ "If this shell still shows the old version, run `hash -r` or open a new terminal."
299
+ );
300
+ return { status, env, upgraded: true, lines };
301
+ }
302
+ lines.push(
303
+ `Installed ${spec}, but PATH still resolves to v${env.binVersion ?? "unknown"} at:`,
304
+ ` ${env.binPath ?? "(unresolved)"}`,
305
+ "Run `hash -r` and `which -a agent-kit`. Until PATH matches, keep using the npx pin above."
306
+ );
307
+ return { status, env, upgraded: true, lines };
308
+ }
309
+
310
+ export {
311
+ isNonInteractive,
312
+ confirmProjectRoot,
313
+ RootRefusedError,
314
+ classifyInstallError,
315
+ npxPinned,
316
+ pathCliStatus,
317
+ syncPathCliToRuntime
318
+ };