@dadado/agent-kit-cli 6.3.0 → 6.5.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 (48) hide show
  1. package/dashboard/dashboard-data.mjs +14 -2
  2. package/dashboard/dashboard.html +190 -32
  3. package/dashboard/lib/chat-sessions.d.mts +63 -0
  4. package/dashboard/lib/chat-sessions.mjs +430 -0
  5. package/dashboard/{logo-cursor.svg → logo-bare-metal.svg} +1 -1
  6. package/dashboard/logo-marketplace.svg +1 -1
  7. package/dashboard/serve.mjs +5 -1
  8. package/dashboard/social-preview.svg +2 -2
  9. package/dist/{add-VA2W7I6P.js → add-IT6XFPKT.js} +2 -2
  10. package/dist/{chunk-NNKOWUWM.js → chunk-236IYK6L.js} +64 -28
  11. package/dist/{chunk-YRFSTHR5.js → chunk-2OIPMQHA.js} +13 -219
  12. package/dist/{chunk-JEI6HACW.js → chunk-2TCRKQHD.js} +35 -379
  13. package/dist/{chunk-U26MRIWN.js → chunk-34BBPQKI.js} +1 -1
  14. package/dist/{chunk-GUQYNUV4.js → chunk-4XZXM2ZA.js} +1 -1
  15. package/dist/{chunk-Z7RYIHHX.js → chunk-5LQP4JGH.js} +3 -3
  16. package/dist/{chunk-6KUSG7BJ.js → chunk-5WSFO35Y.js} +4 -1
  17. package/dist/{chunk-MAPOQEA2.js → chunk-6RRG3WOE.js} +8 -1
  18. package/dist/{chunk-OWWFKGKS.js → chunk-EI3VQ7FU.js} +2 -2
  19. package/dist/{chunk-QTBTKEXK.js → chunk-FM32XR7A.js} +1 -1
  20. package/dist/{chunk-KVY425NM.js → chunk-GIZNM73K.js} +4 -2
  21. package/dist/{chunk-MO63KZBP.js → chunk-HKYJG2FJ.js} +8 -6
  22. package/dist/{chunk-SV2BR2LZ.js → chunk-I2D75F4I.js} +7 -7
  23. package/dist/{chunk-25J2SMJQ.js → chunk-IN4MQ3P3.js} +1 -1
  24. package/dist/{chunk-OVOXRH5W.js → chunk-MEZUW3LL.js} +1 -1
  25. package/dist/chunk-MTLQN57O.js +380 -0
  26. package/dist/chunk-R6WH5P7R.js +223 -0
  27. package/dist/{chunk-VQBI3JVS.js → chunk-TNO7GTAJ.js} +2 -2
  28. package/dist/{chunk-Z7ABX5QI.js → chunk-U7XOLYDG.js} +4 -2
  29. package/dist/{chunk-WMVMBPCR.js → chunk-WOGBBJCX.js} +1 -1
  30. package/dist/{chunk-6GYKOHIL.js → chunk-YIOTJQHL.js} +2 -2
  31. package/dist/{contribute-NLM2BN6Z.js → contribute-V7PV5UMK.js} +3 -3
  32. package/dist/{countdown-QXJD6TDB.js → countdown-YONBTSJ2.js} +10 -8
  33. package/dist/{diff-HHG4JEDE.js → diff-GWIHGH65.js} +4 -4
  34. package/dist/{doctor-TWF2M3S3.js → doctor-FLIQCVFN.js} +8 -8
  35. package/dist/engine-info-UQNVNOA2.js +89 -0
  36. package/dist/{ground-control-NMYYIVCV.js → ground-control-6W2AKTKI.js} +5 -4
  37. package/dist/{guard-EHXF76ID.js → guard-ZZRQW3DJ.js} +107 -8
  38. package/dist/{hook-VP7FHRSZ.js → hook-2SX2V2T6.js} +10 -4
  39. package/dist/index.js +26 -22
  40. package/dist/{init-UOTV4ASJ.js → init-4B2IRH27.js} +11 -11
  41. package/dist/{install-VCHPXQV3.js → install-3JVTG35O.js} +11 -11
  42. package/dist/{run-R66G276Q.js → run-AYT6CRHI.js} +12 -9
  43. package/dist/{run-plan-24Z5K4P3.js → run-plan-5XIISG3W.js} +11 -7
  44. package/dist/sessions-O7MYEMCT.js +343 -0
  45. package/dist/{setup-global-M6LKGJHQ.js → setup-global-6JM5XTAT.js} +5 -5
  46. package/dist/{status-5UKVIKOI.js → status-PMAI7NH3.js} +6 -6
  47. package/dist/{update-VQBGEUWS.js → update-3PLY4FZA.js} +9 -9
  48. package/package.json +1 -1
@@ -1,9 +1,20 @@
1
+ import {
2
+ LineSplitter,
3
+ TurnWatcher,
4
+ askOperator,
5
+ createTerminalAnswerReader,
6
+ detectHitlGate,
7
+ emptyHitlRecord,
8
+ noRelayStop,
9
+ unansweredStop,
10
+ userEventLine
11
+ } from "./chunk-MTLQN57O.js";
1
12
  import {
2
13
  findOnPath
3
14
  } from "./chunk-WGLPZXNU.js";
4
15
  import {
5
16
  HEADLESS_DENY_RULES
6
- } from "./chunk-MAPOQEA2.js";
17
+ } from "./chunk-6RRG3WOE.js";
7
18
  import {
8
19
  HELMET_ACCENT,
9
20
  LABEL_MUTED,
@@ -15,368 +26,12 @@ import {
15
26
  withKoloristColor
16
27
  } from "./chunk-QTON2GQX.js";
17
28
 
18
- // src/plan-loop/hitl-relay.ts
19
- import { createInterface } from "readline";
20
- import { StringDecoder } from "string_decoder";
21
-
22
- // src/plan-loop/line-splitter.ts
23
- var PENDING_MAX_CHARS = 4 * 1024 * 1024;
24
- var LineSplitter = class {
25
- constructor(maxChars = PENDING_MAX_CHARS) {
26
- this.maxChars = maxChars;
27
- }
28
- maxChars;
29
- parts = [];
30
- length = 0;
31
- dropping = false;
32
- /** Calls `onLine` for every line the chunk completes (without the `\n`). */
33
- feed(text, onLine) {
34
- let start = 0;
35
- let nl = text.indexOf("\n", start);
36
- while (nl !== -1) {
37
- const segment = text.slice(start, nl);
38
- if (this.dropping) {
39
- this.dropping = false;
40
- } else if (this.parts.length === 0) {
41
- onLine(segment);
42
- } else {
43
- this.parts.push(segment);
44
- const line3 = this.parts.join("");
45
- this.parts = [];
46
- this.length = 0;
47
- onLine(line3);
48
- }
49
- start = nl + 1;
50
- nl = text.indexOf("\n", start);
51
- }
52
- if (start >= text.length || this.dropping) return;
53
- const tail = start === 0 ? text : text.slice(start);
54
- this.parts.push(tail);
55
- this.length += tail.length;
56
- if (this.length > this.maxChars) {
57
- this.parts = [];
58
- this.length = 0;
59
- this.dropping = true;
60
- }
61
- }
62
- /** The held partial line ("" when none or when it was dropped); resets. */
63
- end() {
64
- const rest = this.dropping ? "" : this.parts.join("");
65
- this.parts = [];
66
- this.length = 0;
67
- this.dropping = false;
68
- return rest;
69
- }
70
- };
71
-
72
- // src/plan-loop/hitl-relay.ts
73
- var HITL_GATE_LINE_RE = /^HITL_GATE:\s*([a-z0-9-]+)\s*\|\s*(.+)$/;
74
- var HITL_REPLY_PREFIX = "HITL_REPLY:";
75
- var RESERVED_GATE_IDS = ["git-prod", "kit-prod"];
76
- var FALLBACK_ASK_ID = "prose-fallback";
77
- var HITL_UNANSWERED_EXIT_CODE = 4;
78
- var HITL_SIGINT_EXIT_CODE = 130;
79
- var NUMBERED_LINE_RE = /^\s*(\d+)\.\s+(.+?)\s*$/;
80
- var FALLBACK_WORDING_RES = [
81
- /reply with (?:the |a )?number/i,
82
- /ask questions is not available/i,
83
- /skip or cancel means stop/i
84
- ];
85
- var TICK_SENTINEL_RE = /LOOP_TICK_RESULT:/;
86
- function parseHitlGateLine(line3) {
87
- const m = HITL_GATE_LINE_RE.exec(line3.trim());
88
- if (!m?.[1] || !m[2]) return null;
89
- const labels = m[2].split("|").map((s) => s.trim()).filter((s) => s.length > 0);
90
- if (labels.length === 0) return null;
91
- return { askId: m[1], labels, detection: "sentinel" };
92
- }
93
- function formatHitlGateLine(gate) {
94
- return `HITL_GATE: ${gate.askId} | ${gate.labels.join(" | ")}`;
95
- }
96
- function findHitlGateInText(text) {
97
- let last = null;
98
- for (const line3 of text.split(/\r?\n/)) {
99
- const gate = parseHitlGateLine(line3);
100
- if (gate) last = gate;
101
- }
102
- return last;
103
- }
104
- function cleanFallbackLabel(raw) {
105
- let label = raw.trim();
106
- const bold = /^\*\*(.+?)\*\*/.exec(label);
107
- if (bold?.[1]) label = bold[1];
108
- else label = label.replace(/\*\*/g, "").replace(/^`(.+)`$/, "$1");
109
- label = label.split(/\s+[—–]\s+/)[0] ?? label;
110
- return label.replace(/[.:]+$/, "").trim();
111
- }
112
- function detectFallbackGate(text) {
113
- if (!FALLBACK_WORDING_RES.some((re) => re.test(text))) return null;
114
- const labels = [];
115
- let expected = 1;
116
- for (const line3 of text.split(/\r?\n/)) {
117
- const m = NUMBERED_LINE_RE.exec(line3);
118
- if (!m?.[1] || !m[2]) continue;
119
- const n = Number(m[1]);
120
- if (n === 1) {
121
- labels.length = 0;
122
- expected = 1;
123
- }
124
- if (n !== expected) continue;
125
- labels.push(cleanFallbackLabel(m[2]));
126
- expected += 1;
127
- }
128
- if (labels.length < 2) return null;
129
- return { askId: FALLBACK_ASK_ID, labels, detection: "fallback" };
130
- }
131
- function detectHitlGate(resultText, assistantTexts) {
132
- if (TICK_SENTINEL_RE.test(resultText)) return null;
133
- const fromResult = findHitlGateInText(resultText);
134
- if (fromResult) return fromResult;
135
- for (let i = assistantTexts.length - 1; i >= 0; i -= 1) {
136
- const text = assistantTexts[i] ?? "";
137
- if (TICK_SENTINEL_RE.test(text)) return null;
138
- const gate = findHitlGateInText(text);
139
- if (gate) return gate;
140
- }
141
- const fallback = detectFallbackGate(resultText);
142
- if (fallback) return fallback;
143
- for (let i = assistantTexts.length - 1; i >= 0; i -= 1) {
144
- const gate = detectFallbackGate(assistantTexts[i] ?? "");
145
- if (gate) return gate;
146
- }
147
- return null;
148
- }
149
- function isReservedGateId(askId) {
150
- return RESERVED_GATE_IDS.includes(askId);
151
- }
152
- var STOP_WORDS = /* @__PURE__ */ new Set(["skip", "cancel"]);
153
- function resolveOperatorAnswer(input, labels) {
154
- const text = input.trim();
155
- if (!text) return { kind: "stop", cause: "empty" };
156
- const exact = labels.indexOf(text);
157
- if (exact !== -1) return { kind: "reply", n: exact + 1, label: labels[exact] ?? text };
158
- if (/^\d+$/.test(text)) {
159
- const n = Number(text);
160
- const label = labels[n - 1];
161
- if (n >= 1 && label !== void 0) return { kind: "reply", n, label };
162
- }
163
- const lower = text.toLowerCase();
164
- if (STOP_WORDS.has(lower)) return { kind: "stop", cause: lower };
165
- return { kind: "other", text };
166
- }
167
- function formatHitlReply(askId, answer) {
168
- if (answer.kind === "reply") {
169
- return `${HITL_REPLY_PREFIX} ${askId} | operator reply ${answer.n} | ${answer.label}`;
170
- }
171
- if (answer.kind === "other") {
172
- return `${HITL_REPLY_PREFIX} ${askId} | operator reply other | ${answer.text}`;
173
- }
174
- throw new Error("a stop answer has no reply stamp");
175
- }
176
- function createTerminalAnswerReader(opts = {}) {
177
- return (_gate, readOpts) => new Promise((resolve) => {
178
- const input = opts.input ?? process.stdin;
179
- const output = opts.output ?? process.stdout;
180
- const terminal = opts.terminal ?? Boolean(input.isTTY);
181
- const rl = createInterface({ input, output, terminal });
182
- let settled = false;
183
- const finish = (answer) => {
184
- if (settled) return;
185
- settled = true;
186
- readOpts.signal?.removeEventListener("abort", onAbort);
187
- rl.close();
188
- if (typeof input.pause === "function") {
189
- input.pause();
190
- }
191
- resolve(answer);
192
- };
193
- const onAbort = () => finish({ kind: "eof" });
194
- if (readOpts.signal?.aborted) {
195
- onAbort();
196
- return;
197
- }
198
- readOpts.signal?.addEventListener("abort", onAbort, { once: true });
199
- rl.on("SIGINT", () => finish({ kind: "sigint" }));
200
- rl.on("close", () => finish({ kind: "eof" }));
201
- rl.question("> ", (line3) => finish({ kind: "line", text: line3 }));
202
- });
203
- }
204
- function emptyHitlRecord() {
205
- return { replies: [], fallbackDetections: 0 };
206
- }
207
- function operatorStop(askId, cause) {
208
- return {
209
- askId,
210
- cause,
211
- message: `stopped-by-operator: gate ${askId}, no reply (${cause})`,
212
- exitCode: cause === "SIGINT" ? HITL_SIGINT_EXIT_CODE : HITL_UNANSWERED_EXIT_CODE
213
- };
214
- }
215
- function operatorQuitStop(key) {
216
- return {
217
- askId: "none",
218
- cause: "quit",
219
- message: `stopped-by-operator: quit (${key}), no gate open`,
220
- exitCode: HITL_SIGINT_EXIT_CODE
221
- };
222
- }
223
- function unansweredStop(askId, cause) {
224
- return {
225
- askId,
226
- cause,
227
- message: `stopped: unanswered gate (${cause})`,
228
- exitCode: HITL_UNANSWERED_EXIT_CODE
229
- };
230
- }
231
- function driverStop(askId, raw) {
232
- const detail = raw.detail ? `: ${raw.detail}` : "";
233
- return {
234
- askId,
235
- cause: raw.cause,
236
- message: raw.cause === "driver stop" ? `stopped-by-operator: gate ${askId}, no reply (driver stop)` : `stopped: unanswered gate (driver protocol error${detail})`,
237
- exitCode: HITL_UNANSWERED_EXIT_CODE
238
- };
239
- }
240
- function noRelayStop(askId, backend) {
241
- return {
242
- askId,
243
- cause: "no relay",
244
- message: `stopped: unanswered gate (backend ${backend} has no relay)`,
245
- exitCode: HITL_UNANSWERED_EXIT_CODE
246
- };
247
- }
248
- function reservedStop(askId) {
249
- return {
250
- askId,
251
- cause: "reserved",
252
- message: `stopped: gate ${askId} is operator-gated; run the /${askId} slash yourself (never headless)`,
253
- exitCode: HITL_UNANSWERED_EXIT_CODE
254
- };
255
- }
256
- function formatGatePrompt(gate) {
257
- const head = gate.detection === "fallback" ? `HITL gate (prose fallback, ask-id ${gate.askId})` : `HITL gate ${gate.askId}`;
258
- const lines = [
259
- "",
260
- `${head}: reply with the number or the label; anything else is sent as "other"; empty, skip, cancel or Ctrl-C stops the run.`,
261
- ...gate.labels.map((label, i) => ` ${i + 1}. ${label}`)
262
- ];
263
- return `${lines.join("\n")}
264
- `;
265
- }
266
- async function askOperator(gate, opts) {
267
- if (isReservedGateId(gate.askId)) return { kind: "stop", stop: reservedStop(gate.askId) };
268
- if (opts.policy === "off") return { kind: "stop", stop: unansweredStop(gate.askId, "--no-hitl") };
269
- if (!opts.isTTY && opts.policy !== "driver") {
270
- return { kind: "stop", stop: unansweredStop(gate.askId, "no TTY") };
271
- }
272
- opts.onPromptStart?.();
273
- let raw;
274
- try {
275
- opts.write(formatGatePrompt(gate));
276
- raw = await opts.readAnswer(gate, { signal: opts.signal });
277
- } finally {
278
- opts.onPromptEnd?.();
279
- }
280
- if (opts.signal?.aborted) {
281
- return { kind: "stop", stop: unansweredStop(gate.askId, "child exited") };
282
- }
283
- if (raw.kind === "eof") return { kind: "stop", stop: operatorStop(gate.askId, "EOF") };
284
- if (raw.kind === "sigint") return { kind: "stop", stop: operatorStop(gate.askId, "SIGINT") };
285
- if (raw.kind === "stop") return { kind: "stop", stop: driverStop(gate.askId, raw) };
286
- const answer = resolveOperatorAnswer(raw.text, gate.labels);
287
- if (answer.kind === "stop") return { kind: "stop", stop: operatorStop(gate.askId, answer.cause) };
288
- const line3 = formatHitlReply(gate.askId, answer);
289
- const stamp = {
290
- askId: gate.askId,
291
- reply: answer.kind === "reply" ? `operator reply ${answer.n}` : "operator reply other",
292
- label: answer.kind === "reply" ? answer.label : answer.text,
293
- line: line3,
294
- at: (/* @__PURE__ */ new Date()).toISOString(),
295
- detection: gate.detection
296
- };
297
- return { kind: "reply", stamp };
298
- }
299
- function formatHitlSummary(record) {
300
- if (!record) return [];
301
- const lines = record.replies.map(
302
- (s) => `HITL ${s.askId}: ${s.reply} (${s.label}) ${s.at}${s.detection === "fallback" ? " [fallback]" : ""}`
303
- );
304
- if (record.fallbackDetections > 0) {
305
- lines.push(`hitl-detect: prose-fallback x${record.fallbackDetections}`);
306
- }
307
- if (record.stop) lines.push(record.stop.message);
308
- return lines;
309
- }
310
- function hitlExitCode(childExitCode, record) {
311
- if (record?.stop) return record.stop.exitCode;
312
- return childExitCode;
313
- }
314
- function userEventLine(text) {
315
- return `${JSON.stringify({ type: "user", message: { role: "user", content: text } })}
316
- `;
317
- }
318
- var TurnWatcher = class {
319
- constructor(onResult) {
320
- this.onResult = onResult;
321
- }
322
- onResult;
323
- lines = new LineSplitter();
324
- assistantTexts = [];
325
- decoder = new StringDecoder("utf8");
326
- feed(chunk) {
327
- const text = typeof chunk === "string" ? chunk : this.decoder.write(chunk);
328
- if (!text) return;
329
- this.lines.feed(text, (line3) => this.take(line3));
330
- }
331
- end() {
332
- this.lines.feed(this.decoder.end(), (line3) => this.take(line3));
333
- const rest = this.lines.end();
334
- if (rest.trim()) this.take(rest);
335
- }
336
- take(line3) {
337
- const trimmed = line3.trim();
338
- if (!trimmed.startsWith("{")) return;
339
- let event;
340
- try {
341
- event = JSON.parse(trimmed);
342
- } catch {
343
- return;
344
- }
345
- if (typeof event !== "object" || event === null) return;
346
- const ev = event;
347
- if (ev.type === "assistant") {
348
- const content = ev.message?.content;
349
- if (typeof content === "string") {
350
- if (content) this.assistantTexts.push(content);
351
- } else if (Array.isArray(content)) {
352
- for (const part of content) {
353
- if (part && typeof part === "object" && part.type === "text" && typeof part.text === "string") {
354
- this.assistantTexts.push(part.text);
355
- }
356
- }
357
- }
358
- return;
359
- }
360
- if (ev.type === "result") {
361
- const texts = this.assistantTexts;
362
- this.assistantTexts = [];
363
- this.onResult({
364
- resultText: typeof ev.result === "string" ? ev.result : "",
365
- assistantTexts: texts,
366
- isError: ev.is_error === true,
367
- subtype: typeof ev.subtype === "string" ? ev.subtype : null,
368
- errors: Array.isArray(ev.errors) ? ev.errors.filter((e) => typeof e === "string") : []
369
- });
370
- }
371
- }
372
- };
373
-
374
29
  // src/plan-loop/backends.ts
375
30
  import { execFileSync as execFileSync2, spawn } from "child_process";
376
31
  import { createWriteStream as createWriteStream2 } from "fs";
377
32
  import { access as access2 } from "fs/promises";
378
33
  import path2 from "path";
379
- import { StringDecoder as StringDecoder4 } from "string_decoder";
34
+ import { StringDecoder as StringDecoder3 } from "string_decoder";
380
35
 
381
36
  // src/plan-loop/codex.ts
382
37
  import { execFileSync } from "child_process";
@@ -701,10 +356,10 @@ var codexBackend = {
701
356
 
702
357
  // src/plan-loop/cursor-acp.ts
703
358
  import { createWriteStream } from "fs";
704
- import { StringDecoder as StringDecoder3 } from "string_decoder";
359
+ import { StringDecoder as StringDecoder2 } from "string_decoder";
705
360
 
706
361
  // src/plan-loop/stream-render.ts
707
- import { StringDecoder as StringDecoder2 } from "string_decoder";
362
+ import { StringDecoder } from "string_decoder";
708
363
  import { trueColor } from "kolorist";
709
364
 
710
365
  // src/plan-loop/stream-events.ts
@@ -784,12 +439,12 @@ function parseAssistant(event) {
784
439
  }
785
440
  return out.length > 0 ? out : [{ kind: "silent" }];
786
441
  }
787
- var HITL_REPLY_PREFIX2 = "HITL_REPLY:";
442
+ var HITL_REPLY_PREFIX = "HITL_REPLY:";
788
443
  function parseUser(event) {
789
444
  const message = event.message;
790
445
  const content = isRecord2(message) ? message.content : void 0;
791
446
  if (typeof content === "string") {
792
- if (event.isReplay === true && content.startsWith(HITL_REPLY_PREFIX2)) {
447
+ if (event.isReplay === true && content.startsWith(HITL_REPLY_PREFIX)) {
793
448
  return [{ kind: "hitl_reply", line: oneLine(content) }];
794
449
  }
795
450
  return [{ kind: "prompt", chars: content.length }];
@@ -807,7 +462,7 @@ function parseUser(event) {
807
462
  line: firstLineOfContent(part.content)
808
463
  });
809
464
  } else if (type === "text" && typeof part.text === "string") {
810
- if (event.isReplay === true && part.text.startsWith(HITL_REPLY_PREFIX2)) {
465
+ if (event.isReplay === true && part.text.startsWith(HITL_REPLY_PREFIX)) {
811
466
  out.push({ kind: "hitl_reply", line: oneLine(part.text) });
812
467
  continue;
813
468
  }
@@ -915,7 +570,7 @@ function parseStreamLine(line3) {
915
570
  }
916
571
 
917
572
  // src/plan-loop/stream-render.ts
918
- var PENDING_MAX_CHARS2 = 4 * 1024 * 1024;
573
+ var PENDING_MAX_CHARS = 4 * 1024 * 1024;
919
574
  var MIN_COLUMNS = 40;
920
575
  function paint(hex, text, color) {
921
576
  if (!color) return text;
@@ -1000,7 +655,7 @@ var StreamRenderer = class {
1000
655
  pending = "";
1001
656
  dropped = false;
1002
657
  textOpen = false;
1003
- decoder = new StringDecoder2("utf8");
658
+ decoder = new StringDecoder("utf8");
1004
659
  write;
1005
660
  color;
1006
661
  columns;
@@ -1026,7 +681,7 @@ var StreamRenderer = class {
1026
681
  }
1027
682
  this.renderLine(line3);
1028
683
  }
1029
- if (this.pending.length > PENDING_MAX_CHARS2) {
684
+ if (this.pending.length > PENDING_MAX_CHARS) {
1030
685
  this.pending = "";
1031
686
  this.dropped = true;
1032
687
  }
@@ -1297,7 +952,7 @@ async function runCursorAcp(opts) {
1297
952
  } else p.resolve(msg.result);
1298
953
  }
1299
954
  };
1300
- const decoder = new StringDecoder3("utf8");
955
+ const decoder = new StringDecoder2("utf8");
1301
956
  const splitter = new LineSplitter();
1302
957
  child.stdout?.on("data", (chunk) => {
1303
958
  splitter.feed(typeof chunk === "string" ? chunk : decoder.write(chunk), take);
@@ -1351,7 +1006,14 @@ async function runCursorAcp(opts) {
1351
1006
  ...errors.length ? { errors } : {}
1352
1007
  })
1353
1008
  );
1354
- lastResult = { resultText: text, assistantTexts: text ? [text] : [], isError, subtype, errors };
1009
+ lastResult = {
1010
+ resultText: text,
1011
+ assistantTexts: text ? [text] : [],
1012
+ isError,
1013
+ subtype,
1014
+ errors,
1015
+ backgroundTasks: 0
1016
+ };
1355
1017
  };
1356
1018
  const failed = (message, subtype = "error") => finishTurn(message, true, subtype, [message]);
1357
1019
  const session = async () => {
@@ -1437,7 +1099,7 @@ var cursorAcpBackend = {
1437
1099
 
1438
1100
  // src/plan-loop/backends.ts
1439
1101
  function createLineTranslator(translate) {
1440
- const decoder = new StringDecoder4("utf8");
1102
+ const decoder = new StringDecoder3("utf8");
1441
1103
  const lines = new LineSplitter();
1442
1104
  const run = (line3, out) => {
1443
1105
  try {
@@ -1492,7 +1154,7 @@ function redactSecrets(text, secrets) {
1492
1154
  var REDACT_HOLD_MAX_CHARS = 64 * 1024;
1493
1155
  var RedactingStreamBuffer = class {
1494
1156
  pending = "";
1495
- decoder = new StringDecoder4("utf8");
1157
+ decoder = new StringDecoder3("utf8");
1496
1158
  secrets;
1497
1159
  keep;
1498
1160
  constructor(secrets) {
@@ -1553,9 +1215,11 @@ var CLAUDE_NESTED_SESSION_KEYS = [
1553
1215
  "CLAUDE_CODE_CHILD_SESSION",
1554
1216
  "CLAUDE_CODE_BRIDGE_SESSION_ID"
1555
1217
  ];
1218
+ var CLAUDE_BG_WAIT_CEILING_ENV = "CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS";
1556
1219
  function claudeChildEnv(overrides) {
1557
1220
  const env = mergeChildEnv(overrides);
1558
1221
  for (const key of CLAUDE_NESTED_SESSION_KEYS) delete env[key];
1222
+ if (!env[CLAUDE_BG_WAIT_CEILING_ENV]) env[CLAUDE_BG_WAIT_CEILING_ENV] = "0";
1559
1223
  return env;
1560
1224
  }
1561
1225
  var CLAUDE_MAX_TURNS_ENV = "AGENT_KIT_CLAUDE_MAX_TURNS";
@@ -1802,7 +1466,7 @@ function createRelay(hitl, child, redactedError) {
1802
1466
  if (record.stop || closed) return;
1803
1467
  const gate = detectHitlGate(resultText, assistantTexts);
1804
1468
  if (!gate) {
1805
- endStdin();
1469
+ if (turn.backgroundTasks === 0) endStdin();
1806
1470
  return;
1807
1471
  }
1808
1472
  if (gate.detection === "fallback") record.fallbackDetections += 1;
@@ -2106,14 +1770,6 @@ function getBackend(id) {
2106
1770
  }
2107
1771
 
2108
1772
  export {
2109
- LineSplitter,
2110
- RESERVED_GATE_IDS,
2111
- HITL_UNANSWERED_EXIT_CODE,
2112
- formatHitlGateLine,
2113
- findHitlGateInText,
2114
- operatorQuitStop,
2115
- formatHitlSummary,
2116
- hitlExitCode,
2117
1773
  codexBackend,
2118
1774
  parseStreamLine,
2119
1775
  renderStreamEvent,
@@ -5,7 +5,7 @@ import {
5
5
  DEFAULT_REGISTRY_REF,
6
6
  DEFAULT_REGISTRY_URL,
7
7
  resolveRegistryRoot
8
- } from "./chunk-6KUSG7BJ.js";
8
+ } from "./chunk-5WSFO35Y.js";
9
9
 
10
10
  // src/lifecycle/resolve-cli.ts
11
11
  async function resolveRegistryFromCli(options) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  whichBinary
3
- } from "./chunk-JEI6HACW.js";
3
+ } from "./chunk-2TCRKQHD.js";
4
4
 
5
5
  // src/plan-loop/detect.ts
6
6
  var DETECT_ORDER = ["cursor-agent", "claude"];
@@ -2,10 +2,10 @@ import {
2
2
  compareSemver,
3
3
  normalizeSemver,
4
4
  readLocalKitVersion
5
- } from "./chunk-6GYKOHIL.js";
5
+ } from "./chunk-YIOTJQHL.js";
6
6
  import {
7
7
  L0_ARTIFACTS
8
- } from "./chunk-25J2SMJQ.js";
8
+ } from "./chunk-IN4MQ3P3.js";
9
9
  import {
10
10
  copyRegistryFile,
11
11
  emptyStats,
@@ -17,7 +17,7 @@ import {
17
17
  recordOutcome,
18
18
  resolveProtectedGlobs,
19
19
  saveManagedHashLedger
20
- } from "./chunk-6KUSG7BJ.js";
20
+ } from "./chunk-5WSFO35Y.js";
21
21
  import {
22
22
  KIT_PACKAGE_SPEC,
23
23
  KIT_VERSION
@@ -695,7 +695,10 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
695
695
  "d92297c4675bf9b91d7aaa39fdfafcf2568c9b8b867c80e8121e6225bcf9d5a3",
696
696
  "5656ec26963f4d43f9c440f4cae65ad7aa3a33a603de13d81400d3cb5acd1b40",
697
697
  "64cfb0dba5d6bcdcd919eaa73fe32e9e34689323d65c70c9ee8aa107bf228677",
698
- "267537b445490788f4c146e0f5e9276b77a6cc4be77abca8f5696d758bbddaf9"
698
+ "267537b445490788f4c146e0f5e9276b77a6cc4be77abca8f5696d758bbddaf9",
699
+ "ae3d264354f2f89509bf1d0565ca3906aef30b7f7bc8f62297764e7d5436329a",
700
+ "f95f94170f26beb4e03d4e24b22139e1aaa6bbb3d4b43d524ea9f12ed296beb4",
701
+ "23e690d5c97eb1f739115b8977a862332fe44da3a4b0888de078cf437cf478b9"
699
702
  ]);
700
703
 
701
704
  // src/lifecycle/paths.ts
@@ -36,8 +36,15 @@ var HEADLESS_DENY_RULES = [
36
36
  ...HEADLESS_ONLY_DENY_RULES
37
37
  ];
38
38
  var INTERACTIVE_DENY_RULES = [...SHARED_DENY_RULES];
39
+ var INTERACTIVE_ALLOW_RULES = [
40
+ "Bash(gh pr merge)",
41
+ "Bash(gh pr merge *)",
42
+ "Bash(glab mr merge)",
43
+ "Bash(glab mr merge *)"
44
+ ];
39
45
 
40
46
  export {
41
47
  HEADLESS_DENY_RULES,
42
- INTERACTIVE_DENY_RULES
48
+ INTERACTIVE_DENY_RULES,
49
+ INTERACTIVE_ALLOW_RULES
43
50
  };
@@ -4,10 +4,10 @@ import {
4
4
  import {
5
5
  compareSemver,
6
6
  normalizeSemver
7
- } from "./chunk-6GYKOHIL.js";
7
+ } from "./chunk-YIOTJQHL.js";
8
8
  import {
9
9
  MANIFEST_RELATIVE_PATH
10
- } from "./chunk-6KUSG7BJ.js";
10
+ } from "./chunk-5WSFO35Y.js";
11
11
  import {
12
12
  KIT_VERSION,
13
13
  pinnedCliSpec
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  gateExitNotePath
3
- } from "./chunk-KVY425NM.js";
3
+ } from "./chunk-GIZNM73K.js";
4
4
 
5
5
  // src/plan-loop/merge-detect.ts
6
6
  async function isAncestor(git, ref, baseRef) {
@@ -3,9 +3,11 @@ import {
3
3
  } from "./chunk-MUTTNRX4.js";
4
4
  import {
5
5
  claudeRedactions,
6
- findHitlGateInText,
7
6
  redactSecrets
8
- } from "./chunk-JEI6HACW.js";
7
+ } from "./chunk-2TCRKQHD.js";
8
+ import {
9
+ findHitlGateInText
10
+ } from "./chunk-MTLQN57O.js";
9
11
  import {
10
12
  findOnPath
11
13
  } from "./chunk-WGLPZXNU.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isBranchInBase
3
- } from "./chunk-QTBTKEXK.js";
3
+ } from "./chunk-FM32XR7A.js";
4
4
  import {
5
5
  GATE_EXIT_BRANCH_PREFIX,
6
6
  GATE_EXIT_NOTE_DIR,
@@ -11,7 +11,7 @@ import {
11
11
  isSafeBaseRef,
12
12
  landGateExit,
13
13
  resolveGateExitRefs
14
- } from "./chunk-KVY425NM.js";
14
+ } from "./chunk-GIZNM73K.js";
15
15
  import {
16
16
  ensurePathIgnored
17
17
  } from "./chunk-MUTTNRX4.js";
@@ -19,12 +19,14 @@ import {
19
19
  ensureDispatchLogPath,
20
20
  readCommandFile,
21
21
  runHeadlessDispatch
22
- } from "./chunk-Z7ABX5QI.js";
22
+ } from "./chunk-U7XOLYDG.js";
23
23
  import {
24
- formatHitlSummary,
25
- hitlExitCode,
26
24
  redactSecrets
27
- } from "./chunk-JEI6HACW.js";
25
+ } from "./chunk-2TCRKQHD.js";
26
+ import {
27
+ formatHitlSummary,
28
+ hitlExitCode
29
+ } from "./chunk-MTLQN57O.js";
28
30
 
29
31
  // src/plan-loop/review-job.ts
30
32
  import { randomBytes } from "crypto";