@a5c-ai/babysitter-sdk 0.0.29 → 0.0.30

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 (36) hide show
  1. package/dist/cli/commands/runIterate.d.ts +32 -0
  2. package/dist/cli/commands/runIterate.d.ts.map +1 -0
  3. package/dist/cli/commands/runIterate.js +143 -0
  4. package/dist/cli/main.d.ts.map +1 -1
  5. package/dist/cli/main.js +50 -485
  6. package/dist/cli/nodeTaskRunner.d.ts.map +1 -1
  7. package/dist/cli/nodeTaskRunner.js +39 -0
  8. package/dist/hooks/dispatcher.d.ts +10 -0
  9. package/dist/hooks/dispatcher.d.ts.map +1 -0
  10. package/dist/hooks/dispatcher.js +164 -0
  11. package/dist/hooks/index.d.ts +15 -0
  12. package/dist/hooks/index.d.ts.map +1 -0
  13. package/dist/hooks/index.js +19 -0
  14. package/dist/hooks/types.d.ts +154 -0
  15. package/dist/hooks/types.d.ts.map +1 -0
  16. package/dist/hooks/types.js +6 -0
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1 -0
  20. package/dist/runtime/createRun.d.ts.map +1 -1
  21. package/dist/runtime/createRun.js +18 -0
  22. package/dist/runtime/hooks/runtime.d.ts +31 -0
  23. package/dist/runtime/hooks/runtime.d.ts.map +1 -0
  24. package/dist/runtime/hooks/runtime.js +67 -0
  25. package/dist/runtime/intrinsics/hook.d.ts +26 -0
  26. package/dist/runtime/intrinsics/hook.d.ts.map +1 -0
  27. package/dist/runtime/intrinsics/hook.js +45 -0
  28. package/dist/runtime/orchestrateIteration.d.ts.map +1 -1
  29. package/dist/runtime/orchestrateIteration.js +42 -0
  30. package/dist/runtime/processContext.d.ts.map +1 -1
  31. package/dist/runtime/processContext.js +2 -0
  32. package/dist/runtime/types.d.ts +6 -0
  33. package/dist/runtime/types.d.ts.map +1 -1
  34. package/package.json +1 -1
  35. package/skills/babysitter/SKILL.md +0 -203
  36. package/skills/babysitter-score/SKILL.md +0 -35
package/dist/cli/main.js CHANGED
@@ -35,11 +35,8 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  })();
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
37
  exports.createBabysitterCli = createBabysitterCli;
38
- const node_child_process_1 = require("node:child_process");
39
38
  const node_fs_1 = require("node:fs");
40
- const node_module_1 = require("node:module");
41
39
  const path = __importStar(require("node:path"));
42
- const os = __importStar(require("node:os"));
43
40
  const nodeTaskRunner_1 = require("./nodeTaskRunner");
44
41
  const orchestrateIteration_1 = require("../runtime/orchestrateIteration");
45
42
  const createRun_1 = require("../runtime/createRun");
@@ -48,17 +45,17 @@ const stateCache_1 = require("../runtime/replay/stateCache");
48
45
  const tasks_1 = require("../storage/tasks");
49
46
  const journal_1 = require("../storage/journal");
50
47
  const runFiles_1 = require("../storage/runFiles");
48
+ const runIterate_1 = require("./commands/runIterate");
51
49
  const USAGE = `Usage:
52
50
  babysitter run:create --process-id <id> --entry <path#export> [--runs-dir <dir>] [--inputs <file>] [--run-id <id>] [--process-revision <rev>] [--request <id>] [--json] [--dry-run]
53
51
  babysitter run:status <runDir> [--runs-dir <dir>] [--json]
54
52
  babysitter run:events <runDir> [--runs-dir <dir>] [--json] [--limit <n>] [--reverse] [--filter-type <type>]
55
53
  babysitter run:rebuild-state <runDir> [--runs-dir <dir>] [--json] [--dry-run]
54
+ babysitter run:iterate <runDir> [--runs-dir <dir>] [--json] [--verbose] [--iteration <n>]
56
55
  babysitter task:run <runDir> <effectId> [--runs-dir <dir>] [--json] [--dry-run]
57
56
  babysitter run:step <runDir> [--runs-dir <dir>] [--json] [--now <iso8601>]
58
- babysitter run:continue <runDir> [--runs-dir <dir>] [--json] [--dry-run] [--auto-node-tasks] [--auto-node-max <n>] [--auto-node-label <text>]
59
57
  babysitter task:list <runDir> [--runs-dir <dir>] [--pending] [--kind <kind>] [--json]
60
58
  babysitter task:show <runDir> <effectId> [--runs-dir <dir>] [--json]
61
- babysitter skill:install [--type <claude|codex|cursor>] [--scope <local|global>] [--force] [--json] [--dry-run]
62
59
 
63
60
  Global flags:
64
61
  --runs-dir <dir> Override the runs directory (defaults to .a5c/runs).
@@ -67,23 +64,15 @@ Global flags:
67
64
  --verbose Log resolved paths and options to stderr for debugging.
68
65
  --help, -h Show this help text.`;
69
66
  const LARGE_RESULT_PREVIEW_LIMIT = 1024 * 1024; // 1 MiB
70
- const DEFAULT_SKILL_TARGET = "codex";
71
- const DEFAULT_SKILL_SCOPE = "local";
72
- const breakpointsRequire = (0, node_module_1.createRequire)(__filename);
73
67
  function parseArgs(argv) {
74
68
  const [initialCommand, ...rest] = argv;
75
69
  const parsed = {
76
70
  command: initialCommand,
77
71
  runsDir: ".a5c/runs",
78
- skillsDir: undefined,
79
- skillType: DEFAULT_SKILL_TARGET,
80
- skillScope: DEFAULT_SKILL_SCOPE,
81
72
  json: false,
82
73
  dryRun: false,
83
74
  verbose: false,
84
- force: false,
85
75
  helpRequested: false,
86
- autoNodeTasks: false,
87
76
  pendingOnly: false,
88
77
  reverseOrder: false,
89
78
  };
@@ -102,18 +91,6 @@ function parseArgs(argv) {
102
91
  parsed.runsDir = expectFlagValue(rest, ++i, "--runs-dir");
103
92
  continue;
104
93
  }
105
- if (arg === "--skills-dir") {
106
- parsed.skillsDir = expectFlagValue(rest, ++i, "--skills-dir");
107
- continue;
108
- }
109
- if (arg === "--type") {
110
- parsed.skillType = expectSkillTarget(expectFlagValue(rest, ++i, "--type"), "--type");
111
- continue;
112
- }
113
- if (arg === "--scope") {
114
- parsed.skillScope = expectSkillScope(expectFlagValue(rest, ++i, "--scope"), "--scope");
115
- continue;
116
- }
117
94
  if (arg === "--json") {
118
95
  parsed.json = true;
119
96
  continue;
@@ -122,18 +99,10 @@ function parseArgs(argv) {
122
99
  parsed.dryRun = true;
123
100
  continue;
124
101
  }
125
- if (arg === "--force") {
126
- parsed.force = true;
127
- continue;
128
- }
129
102
  if (arg === "--verbose") {
130
103
  parsed.verbose = true;
131
104
  continue;
132
105
  }
133
- if (arg === "--auto-node-tasks") {
134
- parsed.autoNodeTasks = true;
135
- continue;
136
- }
137
106
  if (arg === "--pending") {
138
107
  parsed.pendingOnly = true;
139
108
  continue;
@@ -147,6 +116,11 @@ function parseArgs(argv) {
147
116
  parsed.limit = parsePositiveInteger(raw, "--limit");
148
117
  continue;
149
118
  }
119
+ if (arg === "--iteration") {
120
+ const raw = expectFlagValue(rest, ++i, "--iteration");
121
+ parsed.iteration = parsePositiveInteger(raw, "--iteration");
122
+ continue;
123
+ }
150
124
  if (arg === "--reverse") {
151
125
  parsed.reverseOrder = true;
152
126
  continue;
@@ -183,23 +157,11 @@ function parseArgs(argv) {
183
157
  parsed.nowOverride = expectFlagValue(rest, ++i, "--now");
184
158
  continue;
185
159
  }
186
- if (arg === "--auto-node-max") {
187
- const raw = expectFlagValue(rest, ++i, "--auto-node-max");
188
- parsed.autoNodeMax = parsePositiveInteger(raw, "--auto-node-max");
189
- continue;
190
- }
191
- if (arg === "--auto-node-label") {
192
- parsed.autoNodeLabel = expectFlagValue(rest, ++i, "--auto-node-label");
193
- continue;
194
- }
195
160
  positionals.push(arg);
196
161
  }
197
162
  if (parsed.command === "task:run") {
198
163
  [parsed.runDirArg, parsed.effectId] = positionals;
199
164
  }
200
- else if (parsed.command === "run:continue") {
201
- [parsed.runDirArg] = positionals;
202
- }
203
165
  else if (parsed.command === "task:list") {
204
166
  [parsed.runDirArg] = positionals;
205
167
  }
@@ -209,6 +171,9 @@ function parseArgs(argv) {
209
171
  else if (parsed.command === "run:status") {
210
172
  [parsed.runDirArg] = positionals;
211
173
  }
174
+ else if (parsed.command === "run:iterate") {
175
+ [parsed.runDirArg] = positionals;
176
+ }
212
177
  else if (parsed.command === "run:events") {
213
178
  [parsed.runDirArg] = positionals;
214
179
  }
@@ -239,29 +204,6 @@ function parsePositiveInteger(raw, flag) {
239
204
  }
240
205
  return Math.floor(parsed);
241
206
  }
242
- function expectSkillTarget(raw, flag) {
243
- const normalized = raw.trim().toLowerCase();
244
- if (normalized === "claude" || normalized === "codex" || normalized === "cursor") {
245
- return normalized;
246
- }
247
- throw new Error(`${flag} must be one of: claude, codex, cursor`);
248
- }
249
- function expectSkillScope(raw, flag) {
250
- const normalized = raw.trim().toLowerCase();
251
- if (normalized === "local" || normalized === "global") {
252
- return normalized;
253
- }
254
- throw new Error(`${flag} must be one of: local, global`);
255
- }
256
- function resolveSkillsDir(parsed) {
257
- if (parsed.skillsDir) {
258
- return path.resolve(parsed.skillsDir);
259
- }
260
- const scopeBase = parsed.skillScope === "global"
261
- ? path.join(os.homedir(), `.${parsed.skillType}`)
262
- : path.resolve(`.${parsed.skillType}`);
263
- return path.join(scopeBase, "skills");
264
- }
265
207
  function summarizeActions(actions) {
266
208
  return actions.map((action) => ({
267
209
  effectId: action.effectId,
@@ -269,13 +211,6 @@ function summarizeActions(actions) {
269
211
  label: action.label,
270
212
  }));
271
213
  }
272
- function matchesAutoNodeLabel(action, filter) {
273
- if (!filter)
274
- return true;
275
- const needle = filter.toLowerCase();
276
- const haystacks = [action.label, ...(action.labels ?? []), action.effectId];
277
- return haystacks.some((value) => (value ? value.toLowerCase().includes(needle) : false));
278
- }
279
214
  function logPendingActions(actions, options = {}) {
280
215
  const summaries = summarizeActions(actions);
281
216
  if (options.command && options.includeHeader !== false) {
@@ -324,27 +259,6 @@ function logSleepHints(command, actions) {
324
259
  console.error(`[${command}] sleep-until=${iso} effect=${action.effectId}${label}${pendingInfo}`);
325
260
  }
326
261
  }
327
- function logRunContinueStatus(iterationStatus, executedCount, metadataParts, options) {
328
- const parts = [`[run:continue] status=${iterationStatus}`];
329
- if (options.dryRun) {
330
- parts.push("dryRun=true");
331
- }
332
- if (executedCount > 0) {
333
- parts.push(`autoNode=${executedCount}`);
334
- }
335
- parts.push(...metadataParts);
336
- console.error(parts.join(" "));
337
- }
338
- function logAutoRunPlan(nodeSummaries) {
339
- console.error(`[run:continue] dry-run auto-node tasks count=${nodeSummaries.length}`);
340
- if (!nodeSummaries.length) {
341
- return;
342
- }
343
- for (const summary of nodeSummaries) {
344
- const label = summary.label ? ` ${summary.label}` : "";
345
- console.error(` - ${summary.effectId} [${summary.kind}]${label}`);
346
- }
347
- }
348
262
  function formatResolvedEntrypoint(importPath, exportName) {
349
263
  return `${importPath}${exportName ? `#${exportName}` : ""}`;
350
264
  }
@@ -359,140 +273,6 @@ function formatVerboseValue(value) {
359
273
  return String(value);
360
274
  return JSON.stringify(value);
361
275
  }
362
- function resolveBundledSkillsRoot() {
363
- return path.resolve(__dirname, "..", "..", "skills");
364
- }
365
- async function listBundledSkillDirs() {
366
- const root = resolveBundledSkillsRoot();
367
- const entries = await node_fs_1.promises.readdir(root, { withFileTypes: true });
368
- return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
369
- }
370
- async function pathExists(filePath) {
371
- try {
372
- await node_fs_1.promises.stat(filePath);
373
- return true;
374
- }
375
- catch (error) {
376
- const err = error;
377
- if (err.code === "ENOENT") {
378
- return false;
379
- }
380
- throw error;
381
- }
382
- }
383
- function toPosixPath(value) {
384
- return value.replace(/\\/g, "/");
385
- }
386
- function resolveBreakpointsBin() {
387
- const pkgPath = breakpointsRequire.resolve("@a5c-ai/babysitter-breakpoints/package.json");
388
- const pkgDir = path.dirname(pkgPath);
389
- const pkgJson = breakpointsRequire(pkgPath);
390
- let binRelative;
391
- if (typeof pkgJson.bin === "string") {
392
- binRelative = pkgJson.bin;
393
- }
394
- else if (pkgJson.bin && typeof pkgJson.bin === "object") {
395
- binRelative = pkgJson.bin.breakpoints ?? pkgJson.bin["babysitter-breakpoints"] ?? Object.values(pkgJson.bin)[0];
396
- }
397
- if (!binRelative) {
398
- throw new Error("missing bin entry in @a5c-ai/babysitter-breakpoints package.json");
399
- }
400
- return path.resolve(pkgDir, binRelative);
401
- }
402
- async function installBreakpointsSkill(parsed, skillsDir) {
403
- if (parsed.dryRun) {
404
- return { status: "planned", message: "dry-run: skipped breakpoints install" };
405
- }
406
- let binPath;
407
- try {
408
- binPath = resolveBreakpointsBin();
409
- }
410
- catch (error) {
411
- const message = error instanceof Error ? error.message : String(error);
412
- return { status: "error", message };
413
- }
414
- const args = [binPath, "install-skill", "--target", parsed.skillType, "--scope", parsed.skillScope];
415
- if (parsed.skillsDir) {
416
- args.push("--skills-dir", skillsDir);
417
- }
418
- if (parsed.json) {
419
- args.push("--json");
420
- }
421
- const child = (0, node_child_process_1.spawn)(process.execPath, args, {
422
- stdio: parsed.json ? ["ignore", "pipe", "pipe"] : "inherit",
423
- });
424
- const stdoutChunks = [];
425
- const stderrChunks = [];
426
- if (parsed.json) {
427
- child.stdout?.on("data", (chunk) => stdoutChunks.push(Buffer.from(chunk)));
428
- child.stderr?.on("data", (chunk) => stderrChunks.push(Buffer.from(chunk)));
429
- }
430
- const exitCode = await new Promise((resolve) => {
431
- child.on("close", (code) => resolve(code ?? 1));
432
- child.on("error", () => resolve(1));
433
- });
434
- const stdout = parsed.json ? Buffer.concat(stdoutChunks).toString().trim() : undefined;
435
- const stderr = parsed.json ? Buffer.concat(stderrChunks).toString().trim() : undefined;
436
- if (exitCode === 0) {
437
- return { status: "installed", exitCode, stdout: stdout || undefined, stderr: stderr || undefined };
438
- }
439
- const message = stderr || stdout || `breakpoints install-skill exited with code ${exitCode}`;
440
- return { status: "error", exitCode, message, stdout: stdout || undefined, stderr: stderr || undefined };
441
- }
442
- async function installBundledSkillDir(skillName, options) {
443
- const sourceDir = path.join(resolveBundledSkillsRoot(), skillName);
444
- const destinationDir = path.join(options.skillsDir, skillName);
445
- try {
446
- const sourceExists = await pathExists(sourceDir);
447
- if (!sourceExists) {
448
- return {
449
- name: skillName,
450
- status: "error",
451
- sourceDir,
452
- destinationDir,
453
- message: "bundled skill missing",
454
- };
455
- }
456
- const destinationExists = await pathExists(destinationDir);
457
- if (destinationExists && !options.force) {
458
- return {
459
- name: skillName,
460
- status: "skipped",
461
- sourceDir,
462
- destinationDir,
463
- message: "already installed",
464
- };
465
- }
466
- if (options.dryRun) {
467
- return {
468
- name: skillName,
469
- status: "planned",
470
- sourceDir,
471
- destinationDir,
472
- };
473
- }
474
- if (destinationExists && options.force) {
475
- await node_fs_1.promises.rm(destinationDir, { recursive: true, force: true });
476
- }
477
- await node_fs_1.promises.mkdir(options.skillsDir, { recursive: true });
478
- await node_fs_1.promises.cp(sourceDir, destinationDir, { recursive: true });
479
- return {
480
- name: skillName,
481
- status: "installed",
482
- sourceDir,
483
- destinationDir,
484
- };
485
- }
486
- catch (error) {
487
- return {
488
- name: skillName,
489
- status: "error",
490
- sourceDir,
491
- destinationDir,
492
- message: error instanceof Error ? error.message : String(error),
493
- };
494
- }
495
- }
496
276
  function allowSecretLogs(parsed) {
497
277
  if (!parsed.json || !parsed.verbose) {
498
278
  return false;
@@ -745,6 +525,43 @@ async function handleRunStatus(parsed) {
745
525
  console.log(`[run:status] state=${state} last=${lastSummary}${suffix}`);
746
526
  return 0;
747
527
  }
528
+ async function handleRunIterate(parsed) {
529
+ if (!parsed.runDirArg) {
530
+ console.error(USAGE);
531
+ return 1;
532
+ }
533
+ const runDir = resolveRunDir(parsed.runsDir, parsed.runDirArg);
534
+ logVerbose("run:iterate", parsed, {
535
+ runDir,
536
+ iteration: parsed.iteration,
537
+ json: parsed.json,
538
+ verbose: parsed.verbose,
539
+ });
540
+ try {
541
+ const result = await (0, runIterate_1.runIterate)({
542
+ runDir,
543
+ iteration: parsed.iteration,
544
+ verbose: parsed.verbose,
545
+ json: parsed.json,
546
+ });
547
+ if (parsed.json) {
548
+ console.log(JSON.stringify(result, null, 2));
549
+ }
550
+ else {
551
+ const countInfo = result.count ? ` count=${result.count}` : "";
552
+ const actionInfo = result.action ? ` action=${result.action}` : "";
553
+ console.log(`[run:iterate] iteration=${result.iteration} status=${result.status}${actionInfo}${countInfo} reason=${result.reason}`);
554
+ if (result.status === "waiting" && result.until) {
555
+ console.log(`[run:iterate] Waiting until: ${new Date(result.until).toISOString()}`);
556
+ }
557
+ }
558
+ return 0;
559
+ }
560
+ catch (error) {
561
+ console.error(`[run:iterate] Error: ${error instanceof Error ? error.message : String(error)}`);
562
+ return 1;
563
+ }
564
+ }
748
565
  async function handleRunEvents(parsed) {
749
566
  if (!parsed.runDirArg) {
750
567
  console.error(USAGE);
@@ -902,169 +719,6 @@ async function handleTaskRun(parsed) {
902
719
  }
903
720
  return status === "ok" || status === "skipped" ? 0 : 1;
904
721
  }
905
- async function autoRunNodeTasks(runDir, actions, executed) {
906
- for (const action of actions) {
907
- const summary = {
908
- effectId: action.effectId,
909
- kind: action.kind,
910
- label: action.label,
911
- };
912
- executed.push(summary);
913
- const label = summary.label ? ` ${summary.label}` : "";
914
- console.error(`[auto-run] ${summary.effectId} [${summary.kind}]${label}`);
915
- await (0, nodeTaskRunner_1.runNodeTaskFromCli)({
916
- runDir,
917
- effectId: action.effectId,
918
- task: action.taskDef,
919
- invocationKey: action.invocationKey,
920
- dryRun: false,
921
- });
922
- }
923
- }
924
- function emitJsonResult(iteration, context) {
925
- const payload = {
926
- status: iteration.status,
927
- autoRun: { executed: context.executed, pending: context.autoPending },
928
- metadata: context.metadata ?? null,
929
- };
930
- if (iteration.status === "completed") {
931
- payload.output = context.output;
932
- }
933
- else if (iteration.status === "failed") {
934
- payload.error = context.error ?? null;
935
- }
936
- else {
937
- payload.pending = context.pending;
938
- }
939
- console.log(JSON.stringify(payload));
940
- }
941
- async function handleRunContinue(parsed) {
942
- if (!parsed.runDirArg) {
943
- console.error(USAGE);
944
- return 1;
945
- }
946
- if (parsed.nowOverride) {
947
- console.error("[run:continue] --now is not supported; use run:step for single iterations");
948
- return 1;
949
- }
950
- if ((parsed.autoNodeMax !== undefined || parsed.autoNodeLabel) && !parsed.autoNodeTasks) {
951
- console.error("[run:continue] --auto-node-max/--auto-node-label require --auto-node-tasks");
952
- return 1;
953
- }
954
- const runDir = resolveRunDir(parsed.runsDir, parsed.runDirArg);
955
- logVerbose("run:continue", parsed, {
956
- runDir,
957
- dryRun: parsed.dryRun,
958
- json: parsed.json,
959
- autoNodeTasks: parsed.autoNodeTasks,
960
- autoNodeMax: parsed.autoNodeMax ?? null,
961
- autoNodeLabel: parsed.autoNodeLabel ?? null,
962
- });
963
- if (!(await readRunMetadataSafe(runDir, "run:continue")))
964
- return 1;
965
- const stateSnapshot = await readStateCacheSafe(runDir, "run:continue");
966
- const executed = [];
967
- const autoNodeLimit = parsed.autoNodeMax ?? Number.POSITIVE_INFINITY;
968
- let autoNodeRemaining = autoNodeLimit;
969
- let autoNodeLimitLogged = false;
970
- while (true) {
971
- const iteration = await (0, orchestrateIteration_1.orchestrateIteration)({ runDir });
972
- const pendingActions = iteration.status === "waiting" ? iteration.nextActions : undefined;
973
- const pendingCounts = pendingActions ? countActionsByKind(pendingActions) : undefined;
974
- const enrichedMetadata = enrichIterationMetadata(iteration.metadata, pendingActions);
975
- const metadata = mergeMetadataSources(enrichedMetadata, {
976
- snapshot: stateSnapshot,
977
- pendingByKind: pendingCounts,
978
- });
979
- const formattedMetadata = formatIterationMetadata(metadata);
980
- logRunContinueStatus(iteration.status, executed.length, formattedMetadata.textParts, {
981
- dryRun: parsed.dryRun,
982
- });
983
- if (iteration.status === "waiting") {
984
- const pending = logPendingActions(iteration.nextActions, {
985
- command: "run:continue",
986
- includeHeader: false,
987
- });
988
- logSleepHints("run:continue", iteration.nextActions);
989
- const nodeActions = iteration.nextActions.filter((action) => action.kind === "node");
990
- const eligibleAutoActions = parsed.autoNodeTasks
991
- ? nodeActions.filter((action) => matchesAutoNodeLabel(action, parsed.autoNodeLabel))
992
- : nodeActions;
993
- const planCap = parsed.autoNodeTasks
994
- ? Math.min(eligibleAutoActions.length, Number.isFinite(autoNodeRemaining) ? Math.max(0, Math.floor(autoNodeRemaining)) : eligibleAutoActions.length)
995
- : eligibleAutoActions.length;
996
- const plannedAutoActions = eligibleAutoActions.slice(0, planCap);
997
- const nodeSummaries = summarizeActions(nodeActions);
998
- const autoPendingSummaries = parsed.autoNodeTasks ? summarizeActions(plannedAutoActions) : nodeSummaries;
999
- if (parsed.autoNodeTasks && eligibleAutoActions.length > 0 && autoNodeRemaining <= 0 && Number.isFinite(autoNodeLimit)) {
1000
- if (!autoNodeLimitLogged) {
1001
- console.error(`[auto-run] reached --auto-node-max=${parsed.autoNodeMax}`);
1002
- autoNodeLimitLogged = true;
1003
- }
1004
- }
1005
- if (parsed.autoNodeTasks && parsed.autoNodeLabel && eligibleAutoActions.length === 0 && nodeActions.length > 0) {
1006
- console.error(`[auto-run] no node tasks matched --auto-node-label=${parsed.autoNodeLabel}; ${nodeActions.length} pending`);
1007
- }
1008
- if (parsed.autoNodeTasks && plannedAutoActions.length > 0) {
1009
- if (parsed.dryRun) {
1010
- logAutoRunPlan(autoPendingSummaries);
1011
- if (parsed.json) {
1012
- emitJsonResult({ status: "waiting" }, {
1013
- executed,
1014
- pending,
1015
- autoPending: autoPendingSummaries,
1016
- metadata: formattedMetadata.jsonMetadata ?? null,
1017
- });
1018
- }
1019
- return 0;
1020
- }
1021
- await autoRunNodeTasks(runDir, plannedAutoActions, executed);
1022
- if (Number.isFinite(autoNodeRemaining)) {
1023
- autoNodeRemaining = Math.max(0, autoNodeRemaining - plannedAutoActions.length);
1024
- if (autoNodeRemaining <= 0 && !autoNodeLimitLogged && parsed.autoNodeMax !== undefined) {
1025
- console.error(`[auto-run] reached --auto-node-max=${parsed.autoNodeMax}`);
1026
- autoNodeLimitLogged = true;
1027
- }
1028
- }
1029
- continue;
1030
- }
1031
- if (parsed.json) {
1032
- emitJsonResult({ status: "waiting" }, {
1033
- executed,
1034
- pending,
1035
- autoPending: autoPendingSummaries,
1036
- metadata: formattedMetadata.jsonMetadata ?? null,
1037
- });
1038
- }
1039
- return 0;
1040
- }
1041
- if (iteration.status === "completed") {
1042
- if (parsed.json) {
1043
- emitJsonResult({ status: "completed", output: iteration.output }, {
1044
- executed,
1045
- pending: [],
1046
- autoPending: [],
1047
- metadata: formattedMetadata.jsonMetadata ?? null,
1048
- output: iteration.output,
1049
- });
1050
- }
1051
- return 0;
1052
- }
1053
- if (parsed.json) {
1054
- emitJsonResult({ status: "failed", error: iteration.error ?? null }, {
1055
- executed,
1056
- pending: [],
1057
- autoPending: [],
1058
- metadata: formattedMetadata.jsonMetadata ?? null,
1059
- error: iteration.error ?? null,
1060
- });
1061
- }
1062
- else if (iteration.error !== undefined) {
1063
- console.error(iteration.error);
1064
- }
1065
- return 1;
1066
- }
1067
- }
1068
722
  function parseNowOverride(nowOverride) {
1069
723
  if (!nowOverride)
1070
724
  return null;
@@ -1221,92 +875,6 @@ async function handleTaskShow(parsed) {
1221
875
  }
1222
876
  return 0;
1223
877
  }
1224
- async function handleSkillInstall(parsed) {
1225
- const skillsDir = resolveSkillsDir(parsed);
1226
- logVerbose("skill:install", parsed, {
1227
- skillsDir,
1228
- type: parsed.skillType,
1229
- scope: parsed.skillScope,
1230
- dryRun: parsed.dryRun,
1231
- force: parsed.force,
1232
- json: parsed.json,
1233
- });
1234
- const results = [];
1235
- let skillNames;
1236
- try {
1237
- skillNames = await listBundledSkillDirs();
1238
- }
1239
- catch (error) {
1240
- const message = error instanceof Error ? error.message : String(error);
1241
- if (parsed.json) {
1242
- console.log(JSON.stringify({ skillsDir, type: parsed.skillType, scope: parsed.skillScope, error: message, results: [] }));
1243
- }
1244
- else {
1245
- console.error(`[skill:install] failed to read bundled skills: ${message}`);
1246
- }
1247
- return 1;
1248
- }
1249
- if (!skillNames.length) {
1250
- if (parsed.json) {
1251
- console.log(JSON.stringify({ skillsDir, type: parsed.skillType, scope: parsed.skillScope, error: "no bundled skills found", results: [] }));
1252
- }
1253
- else {
1254
- console.error("[skill:install] no bundled skills found");
1255
- }
1256
- return 1;
1257
- }
1258
- for (const skillName of skillNames) {
1259
- results.push(await installBundledSkillDir(skillName, { skillsDir, dryRun: parsed.dryRun, force: parsed.force }));
1260
- }
1261
- const counts = { installed: 0, skipped: 0, planned: 0, error: 0 };
1262
- for (const result of results) {
1263
- if (result.status === "installed")
1264
- counts.installed += 1;
1265
- else if (result.status === "skipped")
1266
- counts.skipped += 1;
1267
- else if (result.status === "planned")
1268
- counts.planned += 1;
1269
- else
1270
- counts.error += 1;
1271
- }
1272
- const breakpointsSummary = await installBreakpointsSkill(parsed, skillsDir);
1273
- const breakpointsFailed = breakpointsSummary.status === "error";
1274
- if (parsed.json) {
1275
- console.log(JSON.stringify({ skillsDir, type: parsed.skillType, scope: parsed.skillScope, results, breakpoints: breakpointsSummary }));
1276
- return counts.error > 0 || breakpointsFailed ? 1 : 0;
1277
- }
1278
- const parts = [`[skill:install] dir=${skillsDir}`];
1279
- if (!parsed.skillsDir) {
1280
- parts.push(`type=${parsed.skillType}`);
1281
- parts.push(`scope=${parsed.skillScope}`);
1282
- }
1283
- if (parsed.dryRun)
1284
- parts.push("dryRun=true");
1285
- if (parsed.force)
1286
- parts.push("force=true");
1287
- parts.push(`breakpoints=${breakpointsSummary.status}`);
1288
- if (counts.installed)
1289
- parts.push(`installed=${counts.installed}`);
1290
- if (counts.skipped)
1291
- parts.push(`skipped=${counts.skipped}`);
1292
- if (counts.planned)
1293
- parts.push(`planned=${counts.planned}`);
1294
- if (counts.error)
1295
- parts.push(`errors=${counts.error}`);
1296
- console.log(parts.join(" "));
1297
- if (breakpointsSummary.status === "error") {
1298
- console.error(`[skill:install] breakpoints install failed: ${breakpointsSummary.message ?? "unknown error"}`);
1299
- }
1300
- for (const result of results) {
1301
- const relativeDest = toPosixPath(path.relative(skillsDir, result.destinationDir));
1302
- const relativeSource = toPosixPath(path.relative(skillsDir, result.sourceDir));
1303
- const destLabel = relativeDest.startsWith("..") ? toPosixPath(result.destinationDir) : relativeDest;
1304
- const sourceLabel = relativeSource.startsWith("..") ? toPosixPath(result.sourceDir) : relativeSource;
1305
- const messageSuffix = result.message ? ` message=${result.message}` : "";
1306
- console.log(`- ${result.name} status=${result.status} dest=${destLabel} src=${sourceLabel}${messageSuffix}`);
1307
- }
1308
- return counts.error > 0 || breakpointsFailed ? 1 : 0;
1309
- }
1310
878
  function toTaskListEntry(record, runDir) {
1311
879
  return {
1312
880
  effectId: record.effectId,
@@ -1578,6 +1146,9 @@ function createBabysitterCli() {
1578
1146
  if (parsed.command === "run:status") {
1579
1147
  return await handleRunStatus(parsed);
1580
1148
  }
1149
+ if (parsed.command === "run:iterate") {
1150
+ return await handleRunIterate(parsed);
1151
+ }
1581
1152
  if (parsed.command === "run:events") {
1582
1153
  return await handleRunEvents(parsed);
1583
1154
  }
@@ -1587,18 +1158,12 @@ function createBabysitterCli() {
1587
1158
  if (parsed.command === "run:step") {
1588
1159
  return await handleRunStep(parsed);
1589
1160
  }
1590
- if (parsed.command === "run:continue") {
1591
- return await handleRunContinue(parsed);
1592
- }
1593
1161
  if (parsed.command === "task:list") {
1594
1162
  return await handleTaskList(parsed);
1595
1163
  }
1596
1164
  if (parsed.command === "task:show") {
1597
1165
  return await handleTaskShow(parsed);
1598
1166
  }
1599
- if (parsed.command === "skill:install") {
1600
- return await handleSkillInstall(parsed);
1601
- }
1602
1167
  console.error(USAGE);
1603
1168
  return 1;
1604
1169
  }
@@ -1 +1 @@
1
- {"version":3,"file":"nodeTaskRunner.d.ts","sourceRoot":"","sources":["../../src/cli/nodeTaskRunner.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAiC,MAAM,sBAAsB,CAAC;AAC5G,OAAO,EAAE,2BAA2B,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE9E,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,kBAAkB,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IACvG,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,2BAA2B,CAAC;CACzC;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA4BtG"}
1
+ {"version":3,"file":"nodeTaskRunner.d.ts","sourceRoot":"","sources":["../../src/cli/nodeTaskRunner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAiC,MAAM,sBAAsB,CAAC;AAC5G,OAAO,EAAE,2BAA2B,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAG9E,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,kBAAkB,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IACvG,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,2BAA2B,CAAC;CACzC;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAqEtG"}