@a5c-ai/babysitter-sdk 0.0.28 → 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.
- package/dist/cli/commands/runIterate.d.ts +32 -0
- package/dist/cli/commands/runIterate.d.ts.map +1 -0
- package/dist/cli/commands/runIterate.js +143 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +50 -485
- package/dist/cli/nodeTaskRunner.d.ts.map +1 -1
- package/dist/cli/nodeTaskRunner.js +39 -0
- package/dist/hooks/dispatcher.d.ts +10 -0
- package/dist/hooks/dispatcher.d.ts.map +1 -0
- package/dist/hooks/dispatcher.js +164 -0
- package/dist/hooks/index.d.ts +15 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +19 -0
- package/dist/hooks/types.d.ts +154 -0
- package/dist/hooks/types.d.ts.map +1 -0
- package/dist/hooks/types.js +6 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/runtime/createRun.d.ts.map +1 -1
- package/dist/runtime/createRun.js +18 -0
- package/dist/runtime/hooks/runtime.d.ts +31 -0
- package/dist/runtime/hooks/runtime.d.ts.map +1 -0
- package/dist/runtime/hooks/runtime.js +67 -0
- package/dist/runtime/intrinsics/hook.d.ts +26 -0
- package/dist/runtime/intrinsics/hook.d.ts.map +1 -0
- package/dist/runtime/intrinsics/hook.js +45 -0
- package/dist/runtime/orchestrateIteration.d.ts.map +1 -1
- package/dist/runtime/orchestrateIteration.js +42 -0
- package/dist/runtime/processContext.d.ts.map +1 -1
- package/dist/runtime/processContext.js +2 -0
- package/dist/runtime/types.d.ts +6 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/skills/babysitter/SKILL.md +0 -203
- 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":"
|
|
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"}
|