@a5c-ai/babysitter-sdk 0.0.170-staging.dae504fd → 0.0.170-staging.dff83fb8

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 (35) hide show
  1. package/dist/cli/commands/hookRun.d.ts +3 -4
  2. package/dist/cli/commands/hookRun.d.ts.map +1 -1
  3. package/dist/cli/commands/hookRun.js +10 -490
  4. package/dist/cli/commands/runIterate.d.ts +0 -3
  5. package/dist/cli/commands/runIterate.d.ts.map +1 -1
  6. package/dist/cli/commands/runIterate.js +90 -15
  7. package/dist/cli/commands/skill.d.ts +49 -0
  8. package/dist/cli/commands/skill.d.ts.map +1 -1
  9. package/dist/cli/commands/skill.js +87 -0
  10. package/dist/cli/main.d.ts.map +1 -1
  11. package/dist/cli/main.js +79 -122
  12. package/dist/harness/claudeCode.d.ts +15 -0
  13. package/dist/harness/claudeCode.d.ts.map +1 -0
  14. package/dist/harness/claudeCode.js +735 -0
  15. package/dist/harness/index.d.ts +5 -0
  16. package/dist/harness/index.d.ts.map +1 -0
  17. package/dist/harness/index.js +14 -0
  18. package/dist/harness/nullAdapter.d.ts +9 -0
  19. package/dist/harness/nullAdapter.d.ts.map +1 -0
  20. package/dist/harness/nullAdapter.js +46 -0
  21. package/dist/harness/registry.d.ts +35 -0
  22. package/dist/harness/registry.d.ts.map +1 -0
  23. package/dist/harness/registry.js +79 -0
  24. package/dist/harness/types.d.ts +60 -0
  25. package/dist/harness/types.d.ts.map +1 -0
  26. package/dist/harness/types.js +10 -0
  27. package/dist/hooks/dispatcher.d.ts +3 -0
  28. package/dist/hooks/dispatcher.d.ts.map +1 -1
  29. package/dist/hooks/dispatcher.js +8 -6
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +1 -0
  33. package/dist/runtime/orchestrateIteration.d.ts.map +1 -1
  34. package/dist/runtime/orchestrateIteration.js +7 -0
  35. package/package.json +1 -1
@@ -1,10 +1,9 @@
1
1
  /**
2
2
  * hook:run CLI command.
3
3
  *
4
- * Replaces heavy bash hook scripts with a single TypeScript command.
5
- * Dispatches to the appropriate handler based on --hook-type:
6
- * - "stop" → handleHookRunStop (replaces babysitter-stop-hook.sh)
7
- * - "session-start" → handleHookRunSessionStart (replaces babysitter-session-start-hook.sh)
4
+ * Dispatches hook handling to the appropriate harness adapter.
5
+ * Each harness (e.g. "claude-code") implements its own stop and
6
+ * session-start handlers via the HarnessAdapter interface.
8
7
  */
9
8
  export interface HookRunCommandArgs {
10
9
  hookType: string;
@@ -1 +1 @@
1
- {"version":3,"file":"hookRun.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/hookRun.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA+EH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAggBD,wBAAsB,aAAa,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiD7E"}
1
+ {"version":3,"file":"hookRun.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/hookRun.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAMD,wBAAsB,aAAa,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmD7E"}
@@ -2,498 +2,16 @@
2
2
  /**
3
3
  * hook:run CLI command.
4
4
  *
5
- * Replaces heavy bash hook scripts with a single TypeScript command.
6
- * Dispatches to the appropriate handler based on --hook-type:
7
- * - "stop" → handleHookRunStop (replaces babysitter-stop-hook.sh)
8
- * - "session-start" → handleHookRunSessionStart (replaces babysitter-session-start-hook.sh)
5
+ * Dispatches hook handling to the appropriate harness adapter.
6
+ * Each harness (e.g. "claude-code") implements its own stop and
7
+ * session-start handlers via the HarnessAdapter interface.
9
8
  */
10
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- var desc = Object.getOwnPropertyDescriptor(m, k);
13
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
- desc = { enumerable: true, get: function() { return m[k]; } };
15
- }
16
- Object.defineProperty(o, k2, desc);
17
- }) : (function(o, m, k, k2) {
18
- if (k2 === undefined) k2 = k;
19
- o[k2] = m[k];
20
- }));
21
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
- Object.defineProperty(o, "default", { enumerable: true, value: v });
23
- }) : function(o, v) {
24
- o["default"] = v;
25
- });
26
- var __importStar = (this && this.__importStar) || (function () {
27
- var ownKeys = function(o) {
28
- ownKeys = Object.getOwnPropertyNames || function (o) {
29
- var ar = [];
30
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
- return ar;
32
- };
33
- return ownKeys(o);
34
- };
35
- return function (mod) {
36
- if (mod && mod.__esModule) return mod;
37
- var result = {};
38
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
- __setModuleDefault(result, mod);
40
- return result;
41
- };
42
- })();
43
9
  Object.defineProperty(exports, "__esModule", { value: true });
44
10
  exports.handleHookRun = handleHookRun;
45
- const path = __importStar(require("node:path"));
46
- const node_fs_1 = require("node:fs");
47
- const journal_1 = require("../../storage/journal");
48
- const runFiles_1 = require("../../storage/runFiles");
49
- const effectIndex_1 = require("../../runtime/replay/effectIndex");
50
- const completionProof_1 = require("../completionProof");
51
- const skill_1 = require("./skill");
52
- const session_1 = require("../../session");
53
- const session_2 = require("./session");
54
- function createHookLogger(hookName) {
55
- const logDir = process.env.BABYSITTER_LOG_DIR;
56
- const logFile = logDir ? path.join(logDir, `${hookName}.log`) : null;
57
- const context = {};
58
- if (logFile) {
59
- try {
60
- (0, node_fs_1.mkdirSync)(logDir, { recursive: true });
61
- }
62
- catch {
63
- // Best-effort
64
- }
65
- }
66
- function write(level, message) {
67
- if (!logFile)
68
- return;
69
- const ts = new Date().toISOString();
70
- const ctxParts = Object.entries(context).map(([k, v]) => `${k}=${v}`);
71
- const ctxStr = ctxParts.length > 0 ? ` [${ctxParts.join(" ")}]` : "";
72
- const line = `[${level}] ${ts}${ctxStr} ${message}\n`;
73
- try {
74
- (0, node_fs_1.appendFileSync)(logFile, line);
75
- }
76
- catch {
77
- // Best-effort
78
- }
79
- }
80
- return {
81
- info: (msg) => write("INFO", msg),
82
- warn: (msg) => write("WARN", msg),
83
- error: (msg) => write("ERROR", msg),
84
- setContext: (key, value) => {
85
- context[key] = value;
86
- },
87
- };
88
- }
89
- // ---------------------------------------------------------------------------
90
- // Stdin reader
91
- // ---------------------------------------------------------------------------
92
- async function readStdin() {
93
- return new Promise((resolve, reject) => {
94
- let data = "";
95
- process.stdin.setEncoding("utf8");
96
- process.stdin.on("data", (chunk) => {
97
- data += chunk;
98
- });
99
- process.stdin.on("end", () => resolve(data));
100
- process.stdin.on("error", reject);
101
- });
102
- }
103
- function parseHookInput(raw) {
104
- const trimmed = raw.trim();
105
- if (!trimmed)
106
- return {};
107
- try {
108
- const parsed = JSON.parse(trimmed);
109
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
110
- return parsed;
111
- }
112
- }
113
- catch {
114
- // Malformed JSON — treat as empty
115
- }
116
- return {};
117
- }
118
- function safeStr(obj, key) {
119
- const val = obj[key];
120
- return typeof val === "string" ? val : "";
121
- }
122
- // ---------------------------------------------------------------------------
123
- // Pending-by-kind helper (mirrors session.ts countPendingByKind)
124
- // ---------------------------------------------------------------------------
125
- function countPendingByKind(records) {
126
- const counts = new Map();
127
- for (const record of records) {
128
- const key = record.kind ?? "unknown";
129
- counts.set(key, (counts.get(key) ?? 0) + 1);
130
- }
131
- return Object.fromEntries(Array.from(counts.entries()).sort(([a], [b]) => a.localeCompare(b)));
132
- }
133
- // ---------------------------------------------------------------------------
134
- // handleHookRunStop — Claude Code "SessionEnd" hook handler
135
- //
136
- // Claude Code-specific: reads {session_id, transcript_path} from stdin,
137
- // outputs {decision: "approve"|"block", reason?, systemMessage?, instructions?}
138
- // ---------------------------------------------------------------------------
139
- async function handleHookRunStop(args) {
140
- const { verbose } = args;
141
- const log = createHookLogger("babysitter-stop-hook");
142
- log.info("handleHookRunStop started");
143
- // 1. Read hook input JSON from stdin
144
- let rawInput;
145
- try {
146
- rawInput = await readStdin();
147
- }
148
- catch (e) {
149
- const msg = e instanceof Error ? e.message : String(e);
150
- log.warn(`stdin read error: ${msg}`);
151
- if (verbose) {
152
- process.stderr.write(`[hook:run stop] stdin read error: ${msg}\n`);
153
- }
154
- // Allow exit on error
155
- process.stdout.write('{"decision":"approve"}\n');
156
- return 0;
157
- }
158
- const hookInput = parseHookInput(rawInput);
159
- log.info("Hook input received");
160
- const sessionId = safeStr(hookInput, "session_id");
161
- if (!sessionId) {
162
- // No session ID — allow exit
163
- log.info("No session ID in hook input — allowing exit");
164
- if (verbose) {
165
- process.stderr.write("[hook:run stop] No session ID in hook input\n");
166
- }
167
- process.stdout.write('{"decision":"approve"}\n');
168
- return 0;
169
- }
170
- log.setContext("session", sessionId);
171
- log.info(`Session ID: ${sessionId}`);
172
- // 2. Resolve pluginRoot and stateDir
173
- const pluginRoot = args.pluginRoot || process.env.CLAUDE_PLUGIN_ROOT || "";
174
- const stateDir = args.stateDir ||
175
- (pluginRoot ? path.join(pluginRoot, "skills", "babysit", "state") : "");
176
- if (!stateDir) {
177
- log.warn("Cannot determine state directory — allowing exit");
178
- if (verbose) {
179
- process.stderr.write("[hook:run stop] Cannot determine state directory\n");
180
- }
181
- process.stdout.write('{"decision":"approve"}\n');
182
- return 0;
183
- }
184
- const runsDir = args.runsDir || ".a5c/runs";
185
- // 3. Check iteration (replaces session:check-iteration CLI call)
186
- const filePath = (0, session_1.getSessionFilePath)(stateDir, sessionId);
187
- log.info(`Checking session at: ${filePath}`);
188
- let sessionFile;
189
- try {
190
- if (!(await (0, session_1.sessionFileExists)(filePath))) {
191
- // No active loop
192
- log.info("No active loop found — allowing exit");
193
- if (verbose) {
194
- process.stderr.write(`[hook:run stop] No active loop found for session ${sessionId}\n`);
195
- }
196
- process.stdout.write('{"decision":"approve"}\n');
197
- return 0;
198
- }
199
- sessionFile = await (0, session_1.readSessionFile)(filePath);
200
- }
201
- catch {
202
- // Cannot read session — allow exit
203
- log.warn("Session file read error — allowing exit");
204
- process.stdout.write('{"decision":"approve"}\n');
205
- return 0;
206
- }
207
- const { state } = sessionFile;
208
- const prompt = sessionFile.prompt ?? "";
209
- // Check max iterations
210
- if (state.maxIterations > 0 && state.iteration >= state.maxIterations) {
211
- if (verbose) {
212
- process.stderr.write(`[hook:run stop] Max iterations (${state.maxIterations}) reached\n`);
213
- }
214
- await cleanupSession(filePath);
215
- process.stdout.write('{"decision":"approve"}\n');
216
- return 0;
217
- }
218
- // Check iteration timing (runaway loop detection)
219
- const now = (0, session_1.getCurrentTimestamp)();
220
- const updatedTimes = state.iteration >= 5
221
- ? (0, session_1.updateIterationTimes)(state.iterationTimes, state.lastIterationAt, now)
222
- : state.iterationTimes;
223
- if ((0, session_1.isIterationTooFast)(updatedTimes)) {
224
- if (verbose) {
225
- const avg = updatedTimes.reduce((a, b) => a + b, 0) / updatedTimes.length;
226
- process.stderr.write(`[hook:run stop] Iteration too fast (avg ${avg}s)\n`);
227
- }
228
- await cleanupSession(filePath);
229
- process.stdout.write('{"decision":"approve"}\n');
230
- return 0;
231
- }
232
- // shouldContinue=true at this point
233
- const iteration = state.iteration;
234
- const maxIterations = state.maxIterations;
235
- const runId = state.runId ?? "";
236
- if (runId) {
237
- log.setContext("run", runId);
238
- }
239
- // 4. Parse transcript for last assistant message
240
- const transcriptPath = safeStr(hookInput, "transcript_path");
241
- let lastText = null;
242
- let hasPromise = false;
243
- let promiseValue = null;
244
- if (transcriptPath) {
245
- const resolvedTranscript = path.resolve(transcriptPath);
246
- if ((0, node_fs_1.existsSync)(resolvedTranscript)) {
247
- try {
248
- const content = (0, node_fs_1.readFileSync)(resolvedTranscript, "utf-8");
249
- const parsed = (0, session_2.parseTranscriptLastAssistantMessage)(content);
250
- lastText = parsed.text;
251
- if (parsed.found && parsed.text) {
252
- promiseValue = (0, session_2.extractPromiseTag)(parsed.text);
253
- hasPromise = promiseValue !== null;
254
- }
255
- }
256
- catch {
257
- // Transcript parse error — cleanup and allow exit
258
- if (verbose) {
259
- process.stderr.write(`[hook:run stop] Transcript parse error: ${resolvedTranscript}\n`);
260
- }
261
- await cleanupSession(filePath);
262
- process.stdout.write('{"decision":"approve"}\n');
263
- return 0;
264
- }
265
- }
266
- else {
267
- if (verbose) {
268
- process.stderr.write(`[hook:run stop] Transcript not found: ${resolvedTranscript}\n`);
269
- }
270
- await cleanupSession(filePath);
271
- process.stdout.write('{"decision":"approve"}\n');
272
- return 0;
273
- }
274
- }
275
- if (!lastText) {
276
- if (verbose) {
277
- process.stderr.write("[hook:run stop] No assistant text content found in transcript\n");
278
- }
279
- await cleanupSession(filePath);
280
- process.stdout.write('{"decision":"approve"}\n');
281
- return 0;
282
- }
283
- // 4b. If no run is associated, there's nothing to iterate on — allow exit
284
- if (!runId) {
285
- log.info("No run associated with session — allowing exit");
286
- if (verbose) {
287
- process.stderr.write(`[hook:run stop] No run associated with session ${sessionId} — allowing exit\n`);
288
- }
289
- await cleanupSession(filePath);
290
- process.stdout.write('{"decision":"approve"}\n');
291
- return 0;
292
- }
293
- // 5. If runId is present, get run status
294
- let runState = "";
295
- let completionProof = "";
296
- let pendingKinds = "";
297
- if (runId) {
298
- try {
299
- const runDir = path.isAbsolute(runId)
300
- ? runId
301
- : path.join(runsDir, runId);
302
- const metadata = await (0, runFiles_1.readRunMetadata)(runDir);
303
- const journal = await (0, journal_1.loadJournal)(runDir);
304
- const index = await (0, effectIndex_1.buildEffectIndex)({ runDir, events: journal });
305
- const hasCompleted = journal.some((e) => e.type === "RUN_COMPLETED");
306
- const hasFailed = journal.some((e) => e.type === "RUN_FAILED");
307
- const pendingRecords = index.listPendingEffects();
308
- const pendingByKind = countPendingByKind(pendingRecords);
309
- const kindKeys = Object.keys(pendingByKind);
310
- if (kindKeys.length > 0) {
311
- pendingKinds = kindKeys.join(", ");
312
- }
313
- if (hasCompleted) {
314
- runState = "completed";
315
- completionProof = (0, completionProof_1.resolveCompletionProof)(metadata);
316
- }
317
- else if (hasFailed) {
318
- runState = "failed";
319
- }
320
- else if (pendingRecords.length > 0) {
321
- runState = "waiting";
322
- }
323
- else {
324
- runState = "created";
325
- }
326
- }
327
- catch {
328
- runState = "";
329
- }
330
- log.info(`Run state: ${runState || "unknown"}`);
331
- if (completionProof) {
332
- log.info("Completion proof available");
333
- }
334
- // If state is empty (couldn't determine) → cleanup and allow
335
- if (!runState) {
336
- if (verbose) {
337
- process.stderr.write(`[hook:run stop] Run state is empty for ${runId}; run may be misconfigured\n`);
338
- }
339
- await cleanupSession(filePath);
340
- process.stdout.write('{"decision":"approve"}\n');
341
- return 0;
342
- }
343
- }
344
- // 6. If completionProof matches promiseValue → complete
345
- if (hasPromise) {
346
- log.info("Detected valid promise tag");
347
- }
348
- if (completionProof && hasPromise && promiseValue === completionProof) {
349
- log.info("Promise matches completion proof — allowing exit");
350
- if (verbose) {
351
- process.stderr.write(`[hook:run stop] Valid promise tag detected - run complete\n`);
352
- }
353
- await cleanupSession(filePath);
354
- process.stdout.write('{"decision":"approve"}\n');
355
- return 0;
356
- }
357
- // 7. Not complete → continue loop
358
- if (!prompt) {
359
- if (verbose) {
360
- process.stderr.write(`[hook:run stop] State file corrupted - no prompt text\n`);
361
- }
362
- await cleanupSession(filePath);
363
- process.stdout.write('{"decision":"approve"}\n');
364
- return 0;
365
- }
366
- const nextIteration = iteration + 1;
367
- const currentTime = (0, session_1.getCurrentTimestamp)();
368
- // Update session state
369
- const updatedState = {
370
- ...state,
371
- iteration: nextIteration,
372
- lastIterationAt: currentTime,
373
- iterationTimes: updatedTimes,
374
- };
375
- try {
376
- await (0, session_1.writeSessionFile)(filePath, updatedState, prompt);
377
- }
378
- catch {
379
- if (verbose) {
380
- process.stderr.write(`[hook:run stop] Failed to update session state\n`);
381
- }
382
- // Continue anyway — state might be stale but loop should work
383
- }
384
- // 8. Build system message
385
- let systemMessage;
386
- if (completionProof) {
387
- systemMessage = `\u{1F504} Babysitter iteration ${nextIteration} | Run completed! To finish: agent must call 'run:status --json' on your run, extract 'completionProof' from the output, then output it in <promise>SECRET</promise> tags. Do not mention or reveal the secret otherwise.`;
388
- }
389
- else if (runState === "waiting" && pendingKinds) {
390
- systemMessage = `\u{1F504} Babysitter iteration ${nextIteration} | Waiting on: ${pendingKinds}. Check if pending effects are resolved, then call run:iterate.`;
391
- }
392
- else if (runState === "failed") {
393
- systemMessage = `\u{1F504} Babysitter iteration ${nextIteration} | Failed. agent must fix the run, journal or process (inspect the sdk.md if needed) and proceed.`;
394
- }
395
- else {
396
- systemMessage = `\u{1F504} Babysitter iteration ${nextIteration} | Agent should continue orchestration (run:iterate)`;
397
- }
398
- // 9. Try to resolve skill context
399
- if (pluginRoot) {
400
- try {
401
- const discoverResult = await (0, skill_1.discoverSkillsInternal)({
402
- pluginRoot,
403
- runId: runId || undefined,
404
- runsDir,
405
- });
406
- if (discoverResult.summary) {
407
- systemMessage = `${systemMessage} | Available skills for this task: ${discoverResult.summary}. Use the Skill tool or skill-discovery to load any of these.`;
408
- }
409
- }
410
- catch {
411
- // Skill discovery failure is non-fatal
412
- }
413
- }
414
- // Cap system message at 1200 chars
415
- if (systemMessage.length > 1200) {
416
- systemMessage = systemMessage.slice(0, 1197) + "...";
417
- }
418
- // 10. Output block decision
419
- const output = {
420
- decision: "block",
421
- instructions: "use the babysitter skill to advance the orchestration to the next state (run:iterate) or perform the pending effects (task:list --pending --json), or fix the run if it failed.",
422
- reason: prompt,
423
- systemMessage,
424
- };
425
- process.stdout.write(JSON.stringify(output) + "\n");
426
- log.info(`Decision: block (iteration=${nextIteration}, maxIterations=${maxIterations})`);
427
- if (verbose) {
428
- process.stderr.write(`[hook:run stop] Blocking stop, iteration=${nextIteration} maxIterations=${maxIterations}\n`);
429
- }
430
- return 0;
431
- }
432
- // ---------------------------------------------------------------------------
433
- // handleHookRunSessionStart — Claude Code "SessionStart" hook handler
434
- //
435
- // Claude Code-specific: reads {session_id} from stdin,
436
- // writes session ID to CLAUDE_ENV_FILE if set, outputs {}
437
- // ---------------------------------------------------------------------------
438
- async function handleHookRunSessionStart(args) {
439
- const { verbose } = args;
440
- // 1. Read hook input JSON from stdin
441
- let rawInput;
442
- try {
443
- rawInput = await readStdin();
444
- }
445
- catch {
446
- process.stdout.write("{}\n");
447
- return 0;
448
- }
449
- finally {
450
- // Unref stdin so it doesn't keep the event loop alive.
451
- // The session-start handler is short-lived and doesn't need stdin after this.
452
- // (The stop handler is unaffected — its shell script pipes from a temp file
453
- // which reaches EOF naturally, so the event loop drains without unref.)
454
- process.stdin.unref();
455
- }
456
- const hookInput = parseHookInput(rawInput);
457
- const sessionId = safeStr(hookInput, "session_id");
458
- if (!sessionId) {
459
- process.stdout.write("{}\n");
460
- return 0;
461
- }
462
- // 2. If CLAUDE_ENV_FILE is set, append session ID export
463
- const envFile = process.env.CLAUDE_ENV_FILE;
464
- if (envFile) {
465
- try {
466
- (0, node_fs_1.appendFileSync)(envFile, `export CLAUDE_SESSION_ID="${sessionId}"\n`);
467
- }
468
- catch {
469
- // Non-fatal — env file write failure
470
- if (verbose) {
471
- process.stderr.write(`[hook:run session-start] Failed to write to CLAUDE_ENV_FILE: ${envFile}\n`);
472
- }
473
- }
474
- }
475
- if (verbose) {
476
- process.stderr.write(`Babysitter session started: ${sessionId}\n`);
477
- }
478
- // 3. Output empty object
479
- process.stdout.write("{}\n");
480
- return 0;
481
- }
482
- // ---------------------------------------------------------------------------
483
- // Cleanup helper
484
- // ---------------------------------------------------------------------------
485
- async function cleanupSession(filePath) {
486
- try {
487
- await (0, session_1.deleteSessionFile)(filePath);
488
- }
489
- catch {
490
- // Best-effort cleanup
491
- }
492
- }
11
+ const harness_1 = require("../../harness");
493
12
  // ---------------------------------------------------------------------------
494
13
  // Main dispatcher
495
14
  // ---------------------------------------------------------------------------
496
- const SUPPORTED_HARNESSES = ["claude-code"];
497
15
  async function handleHookRun(args) {
498
16
  const { hookType, harness, json } = args;
499
17
  if (!hookType) {
@@ -509,10 +27,12 @@ async function handleHookRun(args) {
509
27
  }
510
28
  return 1;
511
29
  }
512
- if (!SUPPORTED_HARNESSES.includes(harness)) {
30
+ const adapter = (0, harness_1.getAdapterByName)(harness);
31
+ if (!adapter) {
32
+ const supported = (0, harness_1.listSupportedHarnesses)();
513
33
  const error = {
514
34
  error: "UNSUPPORTED_HARNESS",
515
- message: `Unsupported harness: "${harness}". Supported: ${SUPPORTED_HARNESSES.join(", ")}`,
35
+ message: `Unsupported harness: "${harness}". Supported: ${supported.join(", ")}`,
516
36
  };
517
37
  if (json) {
518
38
  process.stderr.write(JSON.stringify(error) + "\n");
@@ -524,9 +44,9 @@ async function handleHookRun(args) {
524
44
  }
525
45
  switch (hookType) {
526
46
  case "stop":
527
- return await handleHookRunStop(args);
47
+ return await adapter.handleStopHook(args);
528
48
  case "session-start":
529
- return await handleHookRunSessionStart(args);
49
+ return await adapter.handleSessionStartHook(args);
530
50
  default: {
531
51
  const error = {
532
52
  error: "UNKNOWN_HOOK_TYPE",
@@ -15,7 +15,6 @@ export interface RunIterateOptions {
15
15
  iteration?: number;
16
16
  verbose?: boolean;
17
17
  json?: boolean;
18
- pluginRoot?: string;
19
18
  }
20
19
  export interface RunIterateResult {
21
20
  iteration: number;
@@ -31,8 +30,6 @@ export interface RunIterateResult {
31
30
  runId: string;
32
31
  processId: string;
33
32
  hookStatus?: string;
34
- discoveredSkills?: string[];
35
- discoveredAgents?: string[];
36
33
  };
37
34
  }
38
35
  export declare function runIterate(options: RunIterateOptions): Promise<RunIterateResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"runIterate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/runIterate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKxD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE;QACT,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC5B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC7B,CAAC;CACH;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA+JtF"}
1
+ {"version":3,"file":"runIterate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/runIterate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,qBAAqB,CAAC;AAKzE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE;QACT,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmJtF"}