@adhdev/daemon-standalone 1.0.54-rc.5 → 1.0.54-rc.6

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/index.js CHANGED
@@ -37075,10 +37075,10 @@ var require_dist3 = __commonJS({
37075
37075
  }
37076
37076
  function getDaemonBuildInfo() {
37077
37077
  if (cached2) return cached2;
37078
- const commit = readInjected(true ? "1da9db5183f2455122862392d42c204459fbeb93" : void 0) ?? "unknown";
37079
- const commitShort = readInjected(true ? "1da9db51" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
37080
- const version2 = readInjected(true ? "1.0.54-rc.5" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
37081
- const builtAt = readInjected(true ? "2026-08-17T09:43:09.618Z" : void 0);
37078
+ const commit = readInjected(true ? "c2292e8647ca46416f8cce578c43e98f48999fbc" : void 0) ?? "unknown";
37079
+ const commitShort = readInjected(true ? "c2292e86" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
37080
+ const version2 = readInjected(true ? "1.0.54-rc.6" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
37081
+ const builtAt = readInjected(true ? "2026-08-17T11:05:18.455Z" : void 0);
37082
37082
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
37083
37083
  return cached2;
37084
37084
  }
@@ -66665,6 +66665,7 @@ ${cleanBody}`;
66665
66665
  var import_node_fs4;
66666
66666
  var path20;
66667
66667
  var GIT;
66668
+ var FALSE_COMPLETION_GIT_CHECK_TIMEOUT_MS;
66668
66669
  var TASK_MODE_EVIDENCE_STRATEGY;
66669
66670
  var init_mesh_completion_side_effect_evidence = __esm2({
66670
66671
  "src/mesh/mesh-completion-side-effect-evidence.ts"() {
@@ -66682,6 +66683,7 @@ ${cleanBody}`;
66682
66683
  init_mesh_node_identity();
66683
66684
  init_mesh_work_queue();
66684
66685
  GIT = process.platform === "win32" ? resolveWin32Executable("git") : "git";
66686
+ FALSE_COMPLETION_GIT_CHECK_TIMEOUT_MS = 3e3;
66685
66687
  TASK_MODE_EVIDENCE_STRATEGY = {
66686
66688
  code_change: {
66687
66689
  mode: "code_change",
@@ -66848,32 +66850,6 @@ ${cleanBody}`;
66848
66850
  if (Number.isFinite(acceptedAt) && eventTimestamp < acceptedAt - 2e3) return false;
66849
66851
  return true;
66850
66852
  }
66851
- var AUTHORITATIVE_COMPLETION_MAX_AGE_MS;
66852
- var init_mesh_completion_live_gate = __esm2({
66853
- "src/mesh/mesh-completion-live-gate.ts"() {
66854
- "use strict";
66855
- init_dist();
66856
- init_mesh_turn_ledger();
66857
- init_mesh_events_utils();
66858
- AUTHORITATIVE_COMPLETION_MAX_AGE_MS = 6e4;
66859
- }
66860
- });
66861
- function bootstrapQueueTaskCountsAsHandled(task, bootstrapNodeId, nowMs) {
66862
- if (!meshNodeIdMatches({ id: task.targetNodeId }, bootstrapNodeId)) return false;
66863
- if (task.status === "assigned") return true;
66864
- const al = task.autoLaunch;
66865
- if (!al) return true;
66866
- if (al.status === "started" || al.status === "completed") {
66867
- const launchedAtMs = Date.parse(al.updatedAt);
66868
- return Number.isFinite(launchedAtMs) && nowMs - launchedAtMs < AUTO_LAUNCH_AWAIT_CLAIM_MS;
66869
- }
66870
- return true;
66871
- }
66872
- function resolveCoordinatorDrainDaemonIds(components) {
66873
- const statusInstanceId = readNonEmptyString(components.statusInstanceId);
66874
- const machineId = readNonEmptyString(loadConfig2().machineId);
66875
- return expandDaemonIdForms([statusInstanceId, machineId]);
66876
- }
66877
66853
  function heldCompletionKey(meshId, taskId, attemptId, sessionId, nonce) {
66878
66854
  return `${meshId}${taskId}${attemptId}${sessionId}${nonce}`;
66879
66855
  }
@@ -66903,13 +66879,13 @@ ${cleanBody}`;
66903
66879
  heldLiveStateCompletions.delete(key2);
66904
66880
  continue;
66905
66881
  }
66906
- const live = readLivePendingEvidence(liveInstance);
66882
+ const live = readLiveTurnPendingEvidence(liveInstance);
66907
66883
  if (live.pending) {
66908
66884
  held.nextCheckAt = nowMs + MID_TURN_COMPLETION_HOLD_RETRY_MS;
66909
66885
  continue;
66910
66886
  }
66911
66887
  heldLiveStateCompletions.delete(key2);
66912
- injectMeshSystemMessage(held.components, {
66888
+ held.inject(held.components, {
66913
66889
  meshId: held.meshId,
66914
66890
  sourceInstanceId: held.sourceInstanceId,
66915
66891
  nodeId: held.nodeId,
@@ -66933,7 +66909,7 @@ ${cleanBody}`;
66933
66909
  }
66934
66910
  scheduleHeldLiveStateCompletionDrain();
66935
66911
  }
66936
- function holdCompletionForLiveStateRetry(components, args, eventSessionId, nowMs) {
66912
+ function holdCompletionForLiveStateRetry(components, args, eventSessionId, nowMs, inject) {
66937
66913
  const taskId = readNonEmptyString(args.metadataEvent.taskId);
66938
66914
  const attemptId = readNonEmptyString(args.metadataEvent.attemptId);
66939
66915
  const dispatchNonce = typeof args.metadataEvent.dispatchNonce === "number" ? args.metadataEvent.dispatchNonce : NaN;
@@ -66943,6 +66919,10 @@ ${cleanBody}`;
66943
66919
  if (!heldLiveStateCompletions.has(key2)) {
66944
66920
  heldLiveStateCompletions.set(key2, {
66945
66921
  components,
66922
+ // Sound in practice: the drain always calls `inject` back with the
66923
+ // exact `components` object stored alongside it, so widening the
66924
+ // parameter type here can never surface a narrower object.
66925
+ inject,
66946
66926
  meshId: args.meshId,
66947
66927
  sourceInstanceId: args.sourceInstanceId,
66948
66928
  nodeId: args.nodeId,
@@ -66960,6 +66940,41 @@ ${cleanBody}`;
66960
66940
  scheduleHeldLiveStateCompletionDrain();
66961
66941
  return true;
66962
66942
  }
66943
+ var AUTHORITATIVE_COMPLETION_MAX_AGE_MS;
66944
+ var MID_TURN_COMPLETION_HOLD_RETRY_MS;
66945
+ var MID_TURN_COMPLETION_HOLD_TTL_MS;
66946
+ var heldLiveStateCompletions;
66947
+ var heldLiveStateCompletionTimer;
66948
+ var init_mesh_completion_live_gate = __esm2({
66949
+ "src/mesh/mesh-completion-live-gate.ts"() {
66950
+ "use strict";
66951
+ init_dist();
66952
+ init_mesh_runtime_store();
66953
+ init_mesh_turn_ledger();
66954
+ init_mesh_events_utils();
66955
+ AUTHORITATIVE_COMPLETION_MAX_AGE_MS = 6e4;
66956
+ MID_TURN_COMPLETION_HOLD_RETRY_MS = 250;
66957
+ MID_TURN_COMPLETION_HOLD_TTL_MS = 5e3;
66958
+ heldLiveStateCompletions = /* @__PURE__ */ new Map();
66959
+ heldLiveStateCompletionTimer = null;
66960
+ }
66961
+ });
66962
+ function bootstrapQueueTaskCountsAsHandled(task, bootstrapNodeId, nowMs) {
66963
+ if (!meshNodeIdMatches({ id: task.targetNodeId }, bootstrapNodeId)) return false;
66964
+ if (task.status === "assigned") return true;
66965
+ const al = task.autoLaunch;
66966
+ if (!al) return true;
66967
+ if (al.status === "started" || al.status === "completed") {
66968
+ const launchedAtMs = Date.parse(al.updatedAt);
66969
+ return Number.isFinite(launchedAtMs) && nowMs - launchedAtMs < AUTO_LAUNCH_AWAIT_CLAIM_MS;
66970
+ }
66971
+ return true;
66972
+ }
66973
+ function resolveCoordinatorDrainDaemonIds(components) {
66974
+ const statusInstanceId = readNonEmptyString(components.statusInstanceId);
66975
+ const machineId = readNonEmptyString(loadConfig2().machineId);
66976
+ return expandDaemonIdForms([statusInstanceId, machineId]);
66977
+ }
66963
66978
  function getCachedMeshByWorkspace(workspace) {
66964
66979
  const now = Date.now();
66965
66980
  const cached5 = meshByWorkspaceCache.get(workspace);
@@ -67250,7 +67265,7 @@ ${cleanBody}`;
67250
67265
  if (args.event === "agent:generating_completed" && eventSessionId) {
67251
67266
  const liveInstance = components.instanceManager?.getInstance?.(eventSessionId);
67252
67267
  if (typeof liveInstance?.getLiveTurnPendingEvidence === "function" || typeof liveInstance?.hasLiveTurnPendingEvidence === "function") {
67253
- const live = readLivePendingEvidence(liveInstance);
67268
+ const live = readLiveTurnPendingEvidence(liveInstance);
67254
67269
  if (live.pending) {
67255
67270
  const taskId = readNonEmptyString(args.metadataEvent.taskId);
67256
67271
  const attempt = taskId ? MeshRuntimeStore.getInstance().getCurrentTurnAttempt(args.meshId, taskId) : null;
@@ -67267,7 +67282,7 @@ ${cleanBody}`;
67267
67282
  eventSessionId,
67268
67283
  attempt
67269
67284
  });
67270
- const heldForRetry = retryEligible && holdCompletionForLiveStateRetry(components, args, eventSessionId, Date.now());
67285
+ const heldForRetry = retryEligible && holdCompletionForLiveStateRetry(components, args, eventSessionId, Date.now(), injectMeshSystemMessage);
67271
67286
  LOG2.info("MeshEvents", `Suppressed agent:generating_completed for session ${eventSessionId} (mesh ${args.meshId}): current live evidence remains pending (${live.kind ?? "unknown"}); transcript authority=${authority.authoritative ? "fresh_but_not_newer" : authority.reason}${heldForRetry ? " \u2014 bounded content-free retry armed" : ""}`);
67272
67287
  traceMeshEventDrop("mid_turn_live_state_pending", traceCtx, heldForRetry ? "retry_held" : void 0);
67273
67288
  return {
@@ -68551,12 +68566,6 @@ ${cleanBody}`;
68551
68566
  var REMOTE_IDLE_SESSION_TTL_MS;
68552
68567
  var meshByWorkspaceCache;
68553
68568
  var MESH_WORKSPACE_CACHE_TTL_MS;
68554
- var FALSE_COMPLETION_GIT_CHECK_TIMEOUT_MS;
68555
- var MID_TURN_COMPLETION_HOLD_RETRY_MS;
68556
- var MID_TURN_COMPLETION_HOLD_TTL_MS;
68557
- var heldLiveStateCompletions;
68558
- var heldLiveStateCompletionTimer;
68559
- var readLivePendingEvidence;
68560
68569
  var lastPendingEventsPruneAt;
68561
68570
  var PENDING_EVENTS_PRUNE_INTERVAL_MS;
68562
68571
  var INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS;
@@ -68598,12 +68607,6 @@ ${cleanBody}`;
68598
68607
  REMOTE_IDLE_SESSION_TTL_MS = 5 * 60 * 1e3;
68599
68608
  meshByWorkspaceCache = /* @__PURE__ */ new Map();
68600
68609
  MESH_WORKSPACE_CACHE_TTL_MS = 5e3;
68601
- FALSE_COMPLETION_GIT_CHECK_TIMEOUT_MS = 3e3;
68602
- MID_TURN_COMPLETION_HOLD_RETRY_MS = 250;
68603
- MID_TURN_COMPLETION_HOLD_TTL_MS = 5e3;
68604
- heldLiveStateCompletions = /* @__PURE__ */ new Map();
68605
- heldLiveStateCompletionTimer = null;
68606
- readLivePendingEvidence = readLiveTurnPendingEvidence;
68607
68610
  lastPendingEventsPruneAt = 0;
68608
68611
  PENDING_EVENTS_PRUNE_INTERVAL_MS = 60 * 60 * 1e3;
68609
68612
  INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
@@ -72224,11 +72227,46 @@ ${cleanBody}`;
72224
72227
  const t = spec.pre_launch_trust;
72225
72228
  if (!t || typeof t !== "object" || Array.isArray(t)) {
72226
72229
  errs.push("pre_launch_trust must be an object");
72230
+ } else if (t.scheme !== void 0) {
72231
+ if (t.scheme !== "kimi_workspace_file") errs.push('pre_launch_trust.scheme must be "kimi_workspace_file"');
72232
+ if (t.settings_path !== void 0 || t.key !== void 0) errs.push("pre_launch_trust with scheme excludes settings_path/key");
72227
72233
  } else {
72228
72234
  if (typeof t.settings_path !== "string" || !t.settings_path) errs.push("pre_launch_trust.settings_path is required");
72229
72235
  if (typeof t.key !== "string" || !t.key) errs.push("pre_launch_trust.key is required");
72230
72236
  }
72231
72237
  }
72238
+ if (spec.interactive_prompts !== void 0) {
72239
+ const ip = spec.interactive_prompts;
72240
+ if (!ip || typeof ip !== "object" || Array.isArray(ip)) {
72241
+ errs.push("interactive_prompts must be an object");
72242
+ } else if (ip.scheme !== "claude_tui" && ip.scheme !== "kimi_wire") {
72243
+ errs.push('interactive_prompts.scheme must be "claude_tui" or "kimi_wire"');
72244
+ }
72245
+ }
72246
+ if (spec.startup_dismiss !== void 0) {
72247
+ const d = spec.startup_dismiss;
72248
+ if (!d || typeof d !== "object" || Array.isArray(d)) {
72249
+ errs.push("startup_dismiss must be an object");
72250
+ } else {
72251
+ if (typeof d.key !== "string" || !d.key) errs.push("startup_dismiss.key is required");
72252
+ if (!Array.isArray(d.patterns) || d.patterns.length === 0) {
72253
+ errs.push("startup_dismiss.patterns must be a non-empty array");
72254
+ } else {
72255
+ d.patterns.forEach((p, i) => {
72256
+ const rec = p && typeof p === "object" ? p : {};
72257
+ if (typeof rec.regex !== "string" || !rec.regex) {
72258
+ errs.push(`startup_dismiss.patterns[${i}].regex is required`);
72259
+ return;
72260
+ }
72261
+ try {
72262
+ new RegExp(rec.regex, typeof rec.flags === "string" ? rec.flags : void 0);
72263
+ } catch {
72264
+ errs.push(`startup_dismiss.patterns[${i}].regex does not compile`);
72265
+ }
72266
+ });
72267
+ }
72268
+ }
72269
+ }
72232
72270
  if (spec.refocus_when_stalled_ms !== void 0) {
72233
72271
  if (typeof spec.refocus_when_stalled_ms !== "number" || !(spec.refocus_when_stalled_ms > 0)) {
72234
72272
  errs.push("refocus_when_stalled_ms must be a positive number");
@@ -72344,6 +72382,7 @@ ${cleanBody}`;
72344
72382
  extractButtonsFromRule: () => extractButtonsFromRule,
72345
72383
  extractTitle: () => extractTitle,
72346
72384
  lastContiguousNumberedBlock: () => lastContiguousNumberedBlock,
72385
+ mapButtonKeyToken: () => mapButtonKeyToken,
72347
72386
  resolveSections: () => resolveSections,
72348
72387
  sectionText: () => sectionText
72349
72388
  });
@@ -72564,8 +72603,52 @@ ${cleanBody}`;
72564
72603
  const flags = (ref.flags ?? "m").replace(/g/g, "");
72565
72604
  return new RegExp(ref.pattern, flags);
72566
72605
  }
72606
+ function mapButtonKeyToken(tokenRaw) {
72607
+ const token = tokenRaw.trim().toLowerCase();
72608
+ if (!token) return null;
72609
+ const alternatives = token.split(/\s+or\s+/);
72610
+ const letter = alternatives.find((t) => /^[a-z0-9]$/.test(t));
72611
+ const chosen = letter ?? alternatives[0];
72612
+ if (/^[a-z0-9]$/.test(chosen)) return chosen;
72613
+ switch (chosen) {
72614
+ case "tab":
72615
+ return " ";
72616
+ case "shift+tab":
72617
+ return "\x1B[Z";
72618
+ case "esc":
72619
+ case "escape":
72620
+ return "\x1B";
72621
+ case "enter":
72622
+ case "return":
72623
+ return "\r";
72624
+ case "space":
72625
+ return " ";
72626
+ default:
72627
+ return null;
72628
+ }
72629
+ }
72567
72630
  function extractButtonsFromRule(rule, hay) {
72568
- const keyTemplate = rule.key_for_index;
72631
+ const keyTemplate = rule.key_for_index ?? "{index}";
72632
+ if (rule.label_group !== void 0 || rule.key_group !== void 0) {
72633
+ const labelGroup = rule.label_group ?? 1;
72634
+ const re = compilePattern(rule);
72635
+ const ordinal = [];
72636
+ let om;
72637
+ while ((om = re.exec(hay)) !== null) {
72638
+ const label = String(om[labelGroup] ?? "").trim();
72639
+ if (!label) continue;
72640
+ let key2;
72641
+ if (rule.key_group !== void 0) {
72642
+ const mapped = mapButtonKeyToken(String(om[rule.key_group] ?? ""));
72643
+ if (mapped === null) continue;
72644
+ key2 = mapped;
72645
+ } else {
72646
+ key2 = keyTemplate.replace(/\{index\}/g, String(ordinal.length + 1));
72647
+ }
72648
+ ordinal.push({ index: ordinal.length + 1, label, key: key2, current: hasCursorMarker(om[0]) });
72649
+ }
72650
+ return ordinal;
72651
+ }
72569
72652
  const continuationLines = rule.continuation_lines ?? false;
72570
72653
  const buttons = [];
72571
72654
  if (continuationLines) {
@@ -72616,7 +72699,7 @@ ${cleanBody}`;
72616
72699
  return entries.slice(start);
72617
72700
  }
72618
72701
  function hasCursorMarker(text) {
72619
- return /^\s*[❯›>]/.test(text);
72702
+ return /^\s*[❯›>→]/.test(text);
72620
72703
  }
72621
72704
  var init_evaluator = __esm2({
72622
72705
  "src/providers/spec/evaluator.ts"() {
@@ -73457,8 +73540,15 @@ ${cleanBody}`;
73457
73540
  const slugs = /* @__PURE__ */ new Set();
73458
73541
  for (const w of [wsReal, wsRaw]) {
73459
73542
  if (!w) continue;
73460
- slugs.add(claudeProjectDirName(w));
73461
- slugs.add(claudeProjectDirName(w.replace(/^\/+/, "")));
73543
+ for (const base of [
73544
+ claudeProjectDirName(w),
73545
+ // "-Users-…" (leading dash)
73546
+ claudeProjectDirName(w.replace(/^\/+/, ""))
73547
+ // cursor form, no leading dash
73548
+ ]) {
73549
+ slugs.add(base);
73550
+ slugs.add(base.replace(/-{2,}/g, "-"));
73551
+ }
73462
73552
  }
73463
73553
  const segments = sourcePath.split(path29.sep);
73464
73554
  for (const seg of segments) {
@@ -77753,6 +77843,8 @@ ${cont}` : cont;
77753
77843
  function normalizeStartupDismissConfig(raw) {
77754
77844
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
77755
77845
  const config2 = raw;
77846
+ if (config2.maxAttempts === void 0 && config2.max_attempts !== void 0) config2.maxAttempts = config2.max_attempts;
77847
+ if (config2.windowMs === void 0 && config2.window_ms !== void 0) config2.windowMs = config2.window_ms;
77756
77848
  const key2 = typeof config2.key === "string" && config2.key.length > 0 ? config2.key : null;
77757
77849
  const patternsRaw = Array.isArray(config2.patterns) ? config2.patterns : [];
77758
77850
  const patterns = patternsRaw.map((entry) => {
@@ -100542,6 +100634,7 @@ ${marker}`,
100542
100634
  var fs27 = __toESM2(require("fs"));
100543
100635
  var os20 = __toESM2(require("os"));
100544
100636
  var path33 = __toESM2(require("path"));
100637
+ init_kimi_workspace_trust();
100545
100638
  init_logger();
100546
100639
  function expandHome2(p) {
100547
100640
  if (p === "~") return os20.homedir();
@@ -100556,6 +100649,10 @@ ${marker}`,
100556
100649
  }
100557
100650
  }
100558
100651
  function applyPreLaunchTrust(trust, workingDir) {
100652
+ if ("scheme" in trust) {
100653
+ if (trust.scheme === "kimi_workspace_file") return applyKimiWorkspaceTrust(workingDir);
100654
+ return null;
100655
+ }
100559
100656
  const settingsPath = expandHome2(trust.settings_path);
100560
100657
  const key2 = trust.key;
100561
100658
  const real = realWorkspacePath3(workingDir);
@@ -100588,6 +100685,7 @@ ${marker}`,
100588
100685
  return null;
100589
100686
  }
100590
100687
  }
100688
+ init_startup_dismiss();
100591
100689
  init_logger();
100592
100690
  init_debug_trace();
100593
100691
  init_debug_config();
@@ -100677,6 +100775,13 @@ ${marker}`,
100677
100775
  /** Timer that re-runs evaluate() when a time-condition would flip true
100678
100776
  * with no PTY frame to trigger it. */
100679
100777
  wakeTimer = null;
100778
+ /** Boot-prompt dismissal (CliSpecV4.startup_dismiss — OPENCODE-UPDATE-MODAL
100779
+ * class). Config normalized once at start(); the shared decision engine
100780
+ * bounds writes by spawn window + attempt cap + per-snapshot dedupe. */
100781
+ startupDismissConfig = null;
100782
+ startupDismissState = createStartupDismissState();
100783
+ /** Wall clock at start() — the spawn anchor for the dismiss window. */
100784
+ startupDismissSpawnAt = 0;
100680
100785
  /** Timer driving the focus-gated stall watchdog (refocus_when_stalled_ms).
100681
100786
  * Re-arms itself while the machine is generating so a re-prime can fire
100682
100787
  * even when the PTY has gone completely quiet. */
@@ -100760,6 +100865,9 @@ ${marker}`,
100760
100865
  if (this.spec.pre_launch_trust) {
100761
100866
  applyPreLaunchTrust(this.spec.pre_launch_trust, this.opts.workingDir);
100762
100867
  }
100868
+ this.startupDismissConfig = normalizeStartupDismissConfig(this.spec.startup_dismiss);
100869
+ this.startupDismissState = createStartupDismissState();
100870
+ this.startupDismissSpawnAt = now;
100763
100871
  this.adapter.start();
100764
100872
  this.scheduleSpawnPrime();
100765
100873
  this.scheduleWakeForState();
@@ -100781,6 +100889,27 @@ ${marker}`,
100781
100889
  if (typeof seq2 === "string" && seq2.length > 0) this.adapter.send_keys(seq2);
100782
100890
  }
100783
100891
  }
100892
+ /** Boot-prompt dismissal (CliSpecV4.startup_dismiss). Runs on every
100893
+ * reevaluation; the shared decision engine makes it a cheap no-op outside
100894
+ * the spawn window and bounds writes (attempt cap + per-snapshot dedupe),
100895
+ * so a prompt that survives the key can never become a key-spam loop. */
100896
+ maybeDismissStartupPrompt(screen, now) {
100897
+ if (!this.startupDismissConfig) return;
100898
+ const verdict = decideStartupDismiss(
100899
+ this.startupDismissConfig,
100900
+ this.startupDismissState,
100901
+ screen,
100902
+ this.startupDismissSpawnAt,
100903
+ now
100904
+ );
100905
+ if (!verdict.dismiss) return;
100906
+ recordStartupDismiss(this.startupDismissState, screen);
100907
+ LOG2.info("FsmDriver", `[${this.specTag()}] startup prompt matched /${verdict.matchedPattern}/ \u2014 sending dismiss key (attempt ${this.startupDismissState.attempts})`);
100908
+ try {
100909
+ this.adapter.send_keys(this.startupDismissConfig.key);
100910
+ } catch {
100911
+ }
100912
+ }
100784
100913
  dispatch(cmd) {
100785
100914
  switch (cmd.kind) {
100786
100915
  case "send_message":
@@ -101059,6 +101188,7 @@ ${marker}`,
101059
101188
  reevaluate(forceEmit = false) {
101060
101189
  const now = Date.now();
101061
101190
  const screen = this.adapter.snapshot();
101191
+ this.maybeDismissStartupPrompt(screen, now);
101062
101192
  const cursor = this.adapter.getCursorPosition();
101063
101193
  const currentLines = screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
101064
101194
  this.trackRegionChanges(currentLines, cursor, now);
@@ -101926,6 +102056,8 @@ ${marker}`,
101926
102056
  init_provider_cli_shared();
101927
102057
  init_logger();
101928
102058
  init_interactive_prompt();
102059
+ init_interactive_prompt();
102060
+ init_kimi_pending_question();
101929
102061
  function stripAnsi3(text) {
101930
102062
  return String(text || "").replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
101931
102063
  }
@@ -101948,6 +102080,9 @@ ${marker}`,
101948
102080
  driver;
101949
102081
  /** Common spec fields the adapter reads, present in both v3 and v4. */
101950
102082
  spec;
102083
+ /** Owning session id (session registry / read-path targetSessionId) —
102084
+ * the sidecar-claim owner token for wire-based prompt detection. */
102085
+ owningSessionId;
101951
102086
  lastEvent = null;
101952
102087
  latestState = null;
101953
102088
  latestModal = null;
@@ -102007,8 +102142,10 @@ ${marker}`,
102007
102142
  id: raw.id,
102008
102143
  name: raw.name,
102009
102144
  control_bar: raw.control_bar,
102010
- native_history: raw.native_history
102145
+ native_history: raw.native_history,
102146
+ interactive_prompts: raw.interactive_prompts
102011
102147
  };
102148
+ this.owningSessionId = sessionId;
102012
102149
  this.cliType = this.spec.id;
102013
102150
  this.cliName = this.spec.name;
102014
102151
  this.workingDir = workingDir;
@@ -102040,6 +102177,7 @@ ${marker}`,
102040
102177
  const sessionFields = this.providerSessionId ? { providerSessionId: this.providerSessionId } : {};
102041
102178
  if (this.exited) return { status: "stopped", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
102042
102179
  if (!this.spawned) return { status: "starting", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
102180
+ this.refreshWirePendingQuestion();
102043
102181
  this.maybeRefreshNativeHistory();
102044
102182
  const state = this.latestState;
102045
102183
  if (!state) return { status: "starting", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
@@ -102278,7 +102416,18 @@ ${marker}`,
102278
102416
  async setInteractivePromptResponse(response) {
102279
102417
  const prompt = this.activeInteractivePrompt;
102280
102418
  if (!prompt || prompt.promptId !== response.promptId) throw new Error("Interactive prompt response does not match active prompt");
102281
- if (this.cliType !== "claude-cli") return;
102419
+ const scheme = this.interactivePromptScheme();
102420
+ if (scheme === "kimi_wire") {
102421
+ const steps = prompt.promptId.startsWith(KIMI_TUI_SELECTOR_PROMPT_PREFIX) ? buildKimiSelectorAnswerSteps(prompt, response, this.driver.snapshot()) : buildKimiInteractiveTuiAnswerSteps(prompt, response);
102422
+ for (const step of steps) {
102423
+ this.driver.dispatch({ kind: "pty_write", data: step });
102424
+ await new Promise((resolve31) => setTimeout(resolve31, 180));
102425
+ }
102426
+ this.activeInteractivePrompt = null;
102427
+ this.statusCallback?.();
102428
+ return;
102429
+ }
102430
+ if (scheme !== "claude_tui") return;
102282
102431
  if (this.interactivePromptTransport === "tui") {
102283
102432
  const steps = buildClaudeInteractiveTuiAnswerSteps(prompt, response);
102284
102433
  for (const step of steps) {
@@ -102636,8 +102785,53 @@ ${marker}`,
102636
102785
  return;
102637
102786
  }
102638
102787
  }
102788
+ /**
102789
+ * Resolve the interactive-prompt protocol for this session — the spec's
102790
+ * declared `interactive_prompts.scheme`, with a legacy default: a
102791
+ * 'claude-cli' spec that predates the field keeps the claude_tui protocol
102792
+ * it always had (retire this fallback once the published claude spec
102793
+ * declares the field). Every other spec without the field captures no
102794
+ * interactive prompts, exactly as before.
102795
+ */
102796
+ interactivePromptScheme() {
102797
+ const declared = this.spec.interactive_prompts?.scheme;
102798
+ if (declared === "claude_tui" || declared === "kimi_wire") return declared;
102799
+ return this.cliType === "claude-cli" ? "claude_tui" : null;
102800
+ }
102801
+ /**
102802
+ * kimi_wire scheme: refresh the held AskUserQuestion / built-in selector
102803
+ * prompt on the routine status poll — the spec-path port of the legacy
102804
+ * adapter's refreshKimiPendingQuestion (same wire.jsonl authority, same
102805
+ * every-poll cadence, same fail-open semantics).
102806
+ */
102807
+ refreshWirePendingQuestion() {
102808
+ if (this.interactivePromptScheme() !== "kimi_wire") return;
102809
+ try {
102810
+ let prompt = null;
102811
+ if (this.spec.native_history?.source) {
102812
+ prompt = detectKimiPendingQuestion(this.spec.native_history, {
102813
+ agentType: this.cliType,
102814
+ providerSessionId: this.providerSessionId || void 0,
102815
+ sessionStartedAtMs: this.spawnedAtMs,
102816
+ envOverrides: this.spawnedEnv,
102817
+ workspace: this.workingDir,
102818
+ // Sidecar-claim owner token — without it resolution fails
102819
+ // closed on ambiguity (see the legacy call site's note).
102820
+ instanceId: this.owningSessionId || void 0
102821
+ });
102822
+ }
102823
+ if (!prompt && this.latestState?.status !== "generating") {
102824
+ prompt = detectKimiIdleSelectorPrompt(this.driver.snapshot());
102825
+ }
102826
+ if ((prompt?.promptId ?? null) !== (this.activeInteractivePrompt?.promptId ?? null)) {
102827
+ this.activeInteractivePrompt = prompt;
102828
+ this.statusCallback?.();
102829
+ }
102830
+ } catch {
102831
+ }
102832
+ }
102639
102833
  detectInteractivePromptFromPtyChunk(chunk) {
102640
- if (this.cliType !== "claude-cli" || !chunk) return;
102834
+ if (this.interactivePromptScheme() !== "claude_tui" || !chunk) return;
102641
102835
  this.jsonLineTail += chunk;
102642
102836
  if (this.jsonLineTail.length > 64 * 1024) this.jsonLineTail = this.jsonLineTail.slice(-64 * 1024);
102643
102837
  const lines = this.jsonLineTail.split(/\r?\n/);
@@ -102735,7 +102929,7 @@ ${marker}`,
102735
102929
  * for INTERACTIVE_PROMPT_LOST_GRACE_MS the prompt is genuinely resolved.
102736
102930
  */
102737
102931
  maybeClearResolvedClaudeTuiPrompt() {
102738
- if (this.cliType !== "claude-cli" || !this.activeInteractivePrompt) return;
102932
+ if (this.interactivePromptScheme() !== "claude_tui" || !this.activeInteractivePrompt) return;
102739
102933
  let screenText = "";
102740
102934
  try {
102741
102935
  screenText = this.driver.snapshot();
@@ -102756,7 +102950,7 @@ ${marker}`,
102756
102950
  this.statusCallback?.();
102757
102951
  }
102758
102952
  maybeCaptureClaudeTuiPrompt() {
102759
- if (this.cliType !== "claude-cli" || this.activeInteractivePrompt || this.claudeTuiPromptCaptureInFlight) return;
102953
+ if (this.interactivePromptScheme() !== "claude_tui" || this.activeInteractivePrompt || this.claudeTuiPromptCaptureInFlight) return;
102760
102954
  const screenText = this.driver.snapshot();
102761
102955
  const headers = this.readClaudeTuiHeaders(screenText);
102762
102956
  if (!screenText.includes("Enter to select")) return;
@@ -102805,7 +102999,7 @@ ${marker}`,
102805
102999
  * eventually re-read and repaired.
102806
103000
  */
102807
103001
  maybeUpgradeClaudeTuiMultiSelect() {
102808
- if (this.cliType !== "claude-cli" || this.interactivePromptTransport !== "tui" || !this.activeInteractivePrompt) return;
103002
+ if (this.interactivePromptScheme() !== "claude_tui" || this.interactivePromptTransport !== "tui" || !this.activeInteractivePrompt) return;
102809
103003
  const questions = this.activeInteractivePrompt.questions;
102810
103004
  if (questions.every((q) => q.multiSelect)) return;
102811
103005
  let screenText = "";
@@ -104407,6 +104601,10 @@ ${buttons.join("\n")}`;
104407
104601
  const wedgedGeneratingProven = observedStatus === "generating" && isWedgedGeneratingWithNativeTurnEnd(host);
104408
104602
  if (observedStatus !== "idle" && !wedgedGeneratingProven) return false;
104409
104603
  if (!wedgedGeneratingProven && host.hasAdapterPendingResponse()) return false;
104604
+ const live = host.getLiveTurnPendingEvidence?.();
104605
+ if (live?.pending && (live.kind === "modal" || live.kind === "transcript_tool")) {
104606
+ return false;
104607
+ }
104410
104608
  const taskId = host.completingTurnTaskId();
104411
104609
  if (host.shouldSuppressCompletionReEmit(taskId)) {
104412
104610
  return false;
@@ -104475,6 +104673,8 @@ ${buttons.join("\n")}`;
104475
104673
  const fastCollapsed = !!startedTurnTaskId && !host.hasAdapterPendingResponse() && !host.generatingStartedAt && !host.generatingDebouncePending;
104476
104674
  if (!fastCollapsed) return false;
104477
104675
  if (host.fastCollapseSynthesizedTaskId === startedTurnTaskId) return false;
104676
+ const liveSynth = host.getLiveTurnPendingEvidence?.();
104677
+ if (liveSynth?.pending && (liveSynth.kind === "modal" || liveSynth.kind === "transcript_tool")) return false;
104478
104678
  let fcFinalSummary;
104479
104679
  let fcEvidenceSource = "unavailable";
104480
104680
  try {
@@ -126241,7 +126441,12 @@ async (params) => {
126241
126441
  ctx.json(res, 503, { error: "InstanceManager not available" });
126242
126442
  return;
126243
126443
  }
126244
- const target = findCliTarget(ctx, type2);
126444
+ let instanceId;
126445
+ try {
126446
+ instanceId = new URL(_req.url || "", "http://localhost").searchParams.get("instanceId") || void 0;
126447
+ } catch {
126448
+ }
126449
+ const target = findCliTarget(ctx, type2, instanceId);
126245
126450
  if (!target) {
126246
126451
  const allStates = ctx.instanceManager.collectAllStates();
126247
126452
  ctx.json(res, 404, { error: `No running instance for: ${type2}`, available: allStates.filter((s2) => s2.category === "cli" || s2.category === "acp").map((s2) => s2.type) });