@adhdev/daemon-standalone 1.0.54-rc.4 → 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 ? "968e887537fe755b9b980d794a82e5e5d4b92956" : void 0) ?? "unknown";
37079
- const commitShort = readInjected(true ? "968e8875" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
37080
- const version2 = readInjected(true ? "1.0.54-rc.4" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
37081
- const builtAt = readInjected(true ? "2026-08-17T07:59:30.556Z" : 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
  }
@@ -47825,9 +47825,18 @@ Next step: ${nextStep}`;
47825
47825
  if (input.status !== void 0 && !MESH_MISSION_STATUSES.includes(input.status)) {
47826
47826
  throw new Error(`invalid_mission_status: '${input.status}' (valid: ${MESH_MISSION_STATUSES.join(", ")})`);
47827
47827
  }
47828
- const id = typeof input.id === "string" && input.id.trim() ? input.id.trim() : (0, import_crypto7.randomUUID)();
47828
+ const requestedId = typeof input.id === "string" && input.id.trim() ? input.id.trim() : void 0;
47829
47829
  const store = MeshRuntimeStore.getInstance();
47830
- const existing = store.getMission(meshId, id);
47830
+ if (requestedId) {
47831
+ const target = store.getMission(meshId, requestedId);
47832
+ if (!target) {
47833
+ throw new Error(
47834
+ `mission_not_found: no mission with id '${requestedId}' on this mesh. Omit mission_id to create a new mission, or use mesh_mission_list to get a valid full id.`
47835
+ );
47836
+ }
47837
+ }
47838
+ const id = requestedId ?? (0, import_crypto7.randomUUID)();
47839
+ const existing = requestedId ? store.getMission(meshId, id) : null;
47831
47840
  const prevStatus = existing ? normalizeMissionStatus(existing.status) : null;
47832
47841
  const prevGoal = existing?.goal ?? "";
47833
47842
  const record2 = {
@@ -66656,6 +66665,7 @@ ${cleanBody}`;
66656
66665
  var import_node_fs4;
66657
66666
  var path20;
66658
66667
  var GIT;
66668
+ var FALSE_COMPLETION_GIT_CHECK_TIMEOUT_MS;
66659
66669
  var TASK_MODE_EVIDENCE_STRATEGY;
66660
66670
  var init_mesh_completion_side_effect_evidence = __esm2({
66661
66671
  "src/mesh/mesh-completion-side-effect-evidence.ts"() {
@@ -66673,6 +66683,7 @@ ${cleanBody}`;
66673
66683
  init_mesh_node_identity();
66674
66684
  init_mesh_work_queue();
66675
66685
  GIT = process.platform === "win32" ? resolveWin32Executable("git") : "git";
66686
+ FALSE_COMPLETION_GIT_CHECK_TIMEOUT_MS = 3e3;
66676
66687
  TASK_MODE_EVIDENCE_STRATEGY = {
66677
66688
  code_change: {
66678
66689
  mode: "code_change",
@@ -66839,32 +66850,6 @@ ${cleanBody}`;
66839
66850
  if (Number.isFinite(acceptedAt) && eventTimestamp < acceptedAt - 2e3) return false;
66840
66851
  return true;
66841
66852
  }
66842
- var AUTHORITATIVE_COMPLETION_MAX_AGE_MS;
66843
- var init_mesh_completion_live_gate = __esm2({
66844
- "src/mesh/mesh-completion-live-gate.ts"() {
66845
- "use strict";
66846
- init_dist();
66847
- init_mesh_turn_ledger();
66848
- init_mesh_events_utils();
66849
- AUTHORITATIVE_COMPLETION_MAX_AGE_MS = 6e4;
66850
- }
66851
- });
66852
- function bootstrapQueueTaskCountsAsHandled(task, bootstrapNodeId, nowMs) {
66853
- if (!meshNodeIdMatches({ id: task.targetNodeId }, bootstrapNodeId)) return false;
66854
- if (task.status === "assigned") return true;
66855
- const al = task.autoLaunch;
66856
- if (!al) return true;
66857
- if (al.status === "started" || al.status === "completed") {
66858
- const launchedAtMs = Date.parse(al.updatedAt);
66859
- return Number.isFinite(launchedAtMs) && nowMs - launchedAtMs < AUTO_LAUNCH_AWAIT_CLAIM_MS;
66860
- }
66861
- return true;
66862
- }
66863
- function resolveCoordinatorDrainDaemonIds(components) {
66864
- const statusInstanceId = readNonEmptyString(components.statusInstanceId);
66865
- const machineId = readNonEmptyString(loadConfig2().machineId);
66866
- return expandDaemonIdForms([statusInstanceId, machineId]);
66867
- }
66868
66853
  function heldCompletionKey(meshId, taskId, attemptId, sessionId, nonce) {
66869
66854
  return `${meshId}${taskId}${attemptId}${sessionId}${nonce}`;
66870
66855
  }
@@ -66894,13 +66879,13 @@ ${cleanBody}`;
66894
66879
  heldLiveStateCompletions.delete(key2);
66895
66880
  continue;
66896
66881
  }
66897
- const live = readLivePendingEvidence(liveInstance);
66882
+ const live = readLiveTurnPendingEvidence(liveInstance);
66898
66883
  if (live.pending) {
66899
66884
  held.nextCheckAt = nowMs + MID_TURN_COMPLETION_HOLD_RETRY_MS;
66900
66885
  continue;
66901
66886
  }
66902
66887
  heldLiveStateCompletions.delete(key2);
66903
- injectMeshSystemMessage(held.components, {
66888
+ held.inject(held.components, {
66904
66889
  meshId: held.meshId,
66905
66890
  sourceInstanceId: held.sourceInstanceId,
66906
66891
  nodeId: held.nodeId,
@@ -66924,7 +66909,7 @@ ${cleanBody}`;
66924
66909
  }
66925
66910
  scheduleHeldLiveStateCompletionDrain();
66926
66911
  }
66927
- function holdCompletionForLiveStateRetry(components, args, eventSessionId, nowMs) {
66912
+ function holdCompletionForLiveStateRetry(components, args, eventSessionId, nowMs, inject) {
66928
66913
  const taskId = readNonEmptyString(args.metadataEvent.taskId);
66929
66914
  const attemptId = readNonEmptyString(args.metadataEvent.attemptId);
66930
66915
  const dispatchNonce = typeof args.metadataEvent.dispatchNonce === "number" ? args.metadataEvent.dispatchNonce : NaN;
@@ -66934,6 +66919,10 @@ ${cleanBody}`;
66934
66919
  if (!heldLiveStateCompletions.has(key2)) {
66935
66920
  heldLiveStateCompletions.set(key2, {
66936
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,
66937
66926
  meshId: args.meshId,
66938
66927
  sourceInstanceId: args.sourceInstanceId,
66939
66928
  nodeId: args.nodeId,
@@ -66951,6 +66940,41 @@ ${cleanBody}`;
66951
66940
  scheduleHeldLiveStateCompletionDrain();
66952
66941
  return true;
66953
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
+ }
66954
66978
  function getCachedMeshByWorkspace(workspace) {
66955
66979
  const now = Date.now();
66956
66980
  const cached5 = meshByWorkspaceCache.get(workspace);
@@ -67241,7 +67265,7 @@ ${cleanBody}`;
67241
67265
  if (args.event === "agent:generating_completed" && eventSessionId) {
67242
67266
  const liveInstance = components.instanceManager?.getInstance?.(eventSessionId);
67243
67267
  if (typeof liveInstance?.getLiveTurnPendingEvidence === "function" || typeof liveInstance?.hasLiveTurnPendingEvidence === "function") {
67244
- const live = readLivePendingEvidence(liveInstance);
67268
+ const live = readLiveTurnPendingEvidence(liveInstance);
67245
67269
  if (live.pending) {
67246
67270
  const taskId = readNonEmptyString(args.metadataEvent.taskId);
67247
67271
  const attempt = taskId ? MeshRuntimeStore.getInstance().getCurrentTurnAttempt(args.meshId, taskId) : null;
@@ -67258,7 +67282,7 @@ ${cleanBody}`;
67258
67282
  eventSessionId,
67259
67283
  attempt
67260
67284
  });
67261
- const heldForRetry = retryEligible && holdCompletionForLiveStateRetry(components, args, eventSessionId, Date.now());
67285
+ const heldForRetry = retryEligible && holdCompletionForLiveStateRetry(components, args, eventSessionId, Date.now(), injectMeshSystemMessage);
67262
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" : ""}`);
67263
67287
  traceMeshEventDrop("mid_turn_live_state_pending", traceCtx, heldForRetry ? "retry_held" : void 0);
67264
67288
  return {
@@ -68542,12 +68566,6 @@ ${cleanBody}`;
68542
68566
  var REMOTE_IDLE_SESSION_TTL_MS;
68543
68567
  var meshByWorkspaceCache;
68544
68568
  var MESH_WORKSPACE_CACHE_TTL_MS;
68545
- var FALSE_COMPLETION_GIT_CHECK_TIMEOUT_MS;
68546
- var MID_TURN_COMPLETION_HOLD_RETRY_MS;
68547
- var MID_TURN_COMPLETION_HOLD_TTL_MS;
68548
- var heldLiveStateCompletions;
68549
- var heldLiveStateCompletionTimer;
68550
- var readLivePendingEvidence;
68551
68569
  var lastPendingEventsPruneAt;
68552
68570
  var PENDING_EVENTS_PRUNE_INTERVAL_MS;
68553
68571
  var INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS;
@@ -68589,12 +68607,6 @@ ${cleanBody}`;
68589
68607
  REMOTE_IDLE_SESSION_TTL_MS = 5 * 60 * 1e3;
68590
68608
  meshByWorkspaceCache = /* @__PURE__ */ new Map();
68591
68609
  MESH_WORKSPACE_CACHE_TTL_MS = 5e3;
68592
- FALSE_COMPLETION_GIT_CHECK_TIMEOUT_MS = 3e3;
68593
- MID_TURN_COMPLETION_HOLD_RETRY_MS = 250;
68594
- MID_TURN_COMPLETION_HOLD_TTL_MS = 5e3;
68595
- heldLiveStateCompletions = /* @__PURE__ */ new Map();
68596
- heldLiveStateCompletionTimer = null;
68597
- readLivePendingEvidence = readLiveTurnPendingEvidence;
68598
68610
  lastPendingEventsPruneAt = 0;
68599
68611
  PENDING_EVENTS_PRUNE_INTERVAL_MS = 60 * 60 * 1e3;
68600
68612
  INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
@@ -72215,11 +72227,46 @@ ${cleanBody}`;
72215
72227
  const t = spec.pre_launch_trust;
72216
72228
  if (!t || typeof t !== "object" || Array.isArray(t)) {
72217
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");
72218
72233
  } else {
72219
72234
  if (typeof t.settings_path !== "string" || !t.settings_path) errs.push("pre_launch_trust.settings_path is required");
72220
72235
  if (typeof t.key !== "string" || !t.key) errs.push("pre_launch_trust.key is required");
72221
72236
  }
72222
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
+ }
72223
72270
  if (spec.refocus_when_stalled_ms !== void 0) {
72224
72271
  if (typeof spec.refocus_when_stalled_ms !== "number" || !(spec.refocus_when_stalled_ms > 0)) {
72225
72272
  errs.push("refocus_when_stalled_ms must be a positive number");
@@ -72335,6 +72382,7 @@ ${cleanBody}`;
72335
72382
  extractButtonsFromRule: () => extractButtonsFromRule,
72336
72383
  extractTitle: () => extractTitle,
72337
72384
  lastContiguousNumberedBlock: () => lastContiguousNumberedBlock,
72385
+ mapButtonKeyToken: () => mapButtonKeyToken,
72338
72386
  resolveSections: () => resolveSections,
72339
72387
  sectionText: () => sectionText
72340
72388
  });
@@ -72555,8 +72603,52 @@ ${cleanBody}`;
72555
72603
  const flags = (ref.flags ?? "m").replace(/g/g, "");
72556
72604
  return new RegExp(ref.pattern, flags);
72557
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
+ }
72558
72630
  function extractButtonsFromRule(rule, hay) {
72559
- 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
+ }
72560
72652
  const continuationLines = rule.continuation_lines ?? false;
72561
72653
  const buttons = [];
72562
72654
  if (continuationLines) {
@@ -72607,7 +72699,7 @@ ${cleanBody}`;
72607
72699
  return entries.slice(start);
72608
72700
  }
72609
72701
  function hasCursorMarker(text) {
72610
- return /^\s*[❯›>]/.test(text);
72702
+ return /^\s*[❯›>→]/.test(text);
72611
72703
  }
72612
72704
  var init_evaluator = __esm2({
72613
72705
  "src/providers/spec/evaluator.ts"() {
@@ -73448,8 +73540,15 @@ ${cleanBody}`;
73448
73540
  const slugs = /* @__PURE__ */ new Set();
73449
73541
  for (const w of [wsReal, wsRaw]) {
73450
73542
  if (!w) continue;
73451
- slugs.add(claudeProjectDirName(w));
73452
- 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
+ }
73453
73552
  }
73454
73553
  const segments = sourcePath.split(path29.sep);
73455
73554
  for (const seg of segments) {
@@ -77744,6 +77843,8 @@ ${cont}` : cont;
77744
77843
  function normalizeStartupDismissConfig(raw) {
77745
77844
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
77746
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;
77747
77848
  const key2 = typeof config2.key === "string" && config2.key.length > 0 ? config2.key : null;
77748
77849
  const patternsRaw = Array.isArray(config2.patterns) ? config2.patterns : [];
77749
77850
  const patterns = patternsRaw.map((entry) => {
@@ -100533,6 +100634,7 @@ ${marker}`,
100533
100634
  var fs27 = __toESM2(require("fs"));
100534
100635
  var os20 = __toESM2(require("os"));
100535
100636
  var path33 = __toESM2(require("path"));
100637
+ init_kimi_workspace_trust();
100536
100638
  init_logger();
100537
100639
  function expandHome2(p) {
100538
100640
  if (p === "~") return os20.homedir();
@@ -100547,6 +100649,10 @@ ${marker}`,
100547
100649
  }
100548
100650
  }
100549
100651
  function applyPreLaunchTrust(trust, workingDir) {
100652
+ if ("scheme" in trust) {
100653
+ if (trust.scheme === "kimi_workspace_file") return applyKimiWorkspaceTrust(workingDir);
100654
+ return null;
100655
+ }
100550
100656
  const settingsPath = expandHome2(trust.settings_path);
100551
100657
  const key2 = trust.key;
100552
100658
  const real = realWorkspacePath3(workingDir);
@@ -100579,6 +100685,7 @@ ${marker}`,
100579
100685
  return null;
100580
100686
  }
100581
100687
  }
100688
+ init_startup_dismiss();
100582
100689
  init_logger();
100583
100690
  init_debug_trace();
100584
100691
  init_debug_config();
@@ -100668,6 +100775,13 @@ ${marker}`,
100668
100775
  /** Timer that re-runs evaluate() when a time-condition would flip true
100669
100776
  * with no PTY frame to trigger it. */
100670
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;
100671
100785
  /** Timer driving the focus-gated stall watchdog (refocus_when_stalled_ms).
100672
100786
  * Re-arms itself while the machine is generating so a re-prime can fire
100673
100787
  * even when the PTY has gone completely quiet. */
@@ -100751,6 +100865,9 @@ ${marker}`,
100751
100865
  if (this.spec.pre_launch_trust) {
100752
100866
  applyPreLaunchTrust(this.spec.pre_launch_trust, this.opts.workingDir);
100753
100867
  }
100868
+ this.startupDismissConfig = normalizeStartupDismissConfig(this.spec.startup_dismiss);
100869
+ this.startupDismissState = createStartupDismissState();
100870
+ this.startupDismissSpawnAt = now;
100754
100871
  this.adapter.start();
100755
100872
  this.scheduleSpawnPrime();
100756
100873
  this.scheduleWakeForState();
@@ -100772,6 +100889,27 @@ ${marker}`,
100772
100889
  if (typeof seq2 === "string" && seq2.length > 0) this.adapter.send_keys(seq2);
100773
100890
  }
100774
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
+ }
100775
100913
  dispatch(cmd) {
100776
100914
  switch (cmd.kind) {
100777
100915
  case "send_message":
@@ -101050,6 +101188,7 @@ ${marker}`,
101050
101188
  reevaluate(forceEmit = false) {
101051
101189
  const now = Date.now();
101052
101190
  const screen = this.adapter.snapshot();
101191
+ this.maybeDismissStartupPrompt(screen, now);
101053
101192
  const cursor = this.adapter.getCursorPosition();
101054
101193
  const currentLines = screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
101055
101194
  this.trackRegionChanges(currentLines, cursor, now);
@@ -101917,6 +102056,8 @@ ${marker}`,
101917
102056
  init_provider_cli_shared();
101918
102057
  init_logger();
101919
102058
  init_interactive_prompt();
102059
+ init_interactive_prompt();
102060
+ init_kimi_pending_question();
101920
102061
  function stripAnsi3(text) {
101921
102062
  return String(text || "").replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
101922
102063
  }
@@ -101939,6 +102080,9 @@ ${marker}`,
101939
102080
  driver;
101940
102081
  /** Common spec fields the adapter reads, present in both v3 and v4. */
101941
102082
  spec;
102083
+ /** Owning session id (session registry / read-path targetSessionId) —
102084
+ * the sidecar-claim owner token for wire-based prompt detection. */
102085
+ owningSessionId;
101942
102086
  lastEvent = null;
101943
102087
  latestState = null;
101944
102088
  latestModal = null;
@@ -101998,8 +102142,10 @@ ${marker}`,
101998
102142
  id: raw.id,
101999
102143
  name: raw.name,
102000
102144
  control_bar: raw.control_bar,
102001
- native_history: raw.native_history
102145
+ native_history: raw.native_history,
102146
+ interactive_prompts: raw.interactive_prompts
102002
102147
  };
102148
+ this.owningSessionId = sessionId;
102003
102149
  this.cliType = this.spec.id;
102004
102150
  this.cliName = this.spec.name;
102005
102151
  this.workingDir = workingDir;
@@ -102031,6 +102177,7 @@ ${marker}`,
102031
102177
  const sessionFields = this.providerSessionId ? { providerSessionId: this.providerSessionId } : {};
102032
102178
  if (this.exited) return { status: "stopped", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
102033
102179
  if (!this.spawned) return { status: "starting", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
102180
+ this.refreshWirePendingQuestion();
102034
102181
  this.maybeRefreshNativeHistory();
102035
102182
  const state = this.latestState;
102036
102183
  if (!state) return { status: "starting", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
@@ -102269,7 +102416,18 @@ ${marker}`,
102269
102416
  async setInteractivePromptResponse(response) {
102270
102417
  const prompt = this.activeInteractivePrompt;
102271
102418
  if (!prompt || prompt.promptId !== response.promptId) throw new Error("Interactive prompt response does not match active prompt");
102272
- 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;
102273
102431
  if (this.interactivePromptTransport === "tui") {
102274
102432
  const steps = buildClaudeInteractiveTuiAnswerSteps(prompt, response);
102275
102433
  for (const step of steps) {
@@ -102627,8 +102785,53 @@ ${marker}`,
102627
102785
  return;
102628
102786
  }
102629
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
+ }
102630
102833
  detectInteractivePromptFromPtyChunk(chunk) {
102631
- if (this.cliType !== "claude-cli" || !chunk) return;
102834
+ if (this.interactivePromptScheme() !== "claude_tui" || !chunk) return;
102632
102835
  this.jsonLineTail += chunk;
102633
102836
  if (this.jsonLineTail.length > 64 * 1024) this.jsonLineTail = this.jsonLineTail.slice(-64 * 1024);
102634
102837
  const lines = this.jsonLineTail.split(/\r?\n/);
@@ -102726,7 +102929,7 @@ ${marker}`,
102726
102929
  * for INTERACTIVE_PROMPT_LOST_GRACE_MS the prompt is genuinely resolved.
102727
102930
  */
102728
102931
  maybeClearResolvedClaudeTuiPrompt() {
102729
- if (this.cliType !== "claude-cli" || !this.activeInteractivePrompt) return;
102932
+ if (this.interactivePromptScheme() !== "claude_tui" || !this.activeInteractivePrompt) return;
102730
102933
  let screenText = "";
102731
102934
  try {
102732
102935
  screenText = this.driver.snapshot();
@@ -102747,7 +102950,7 @@ ${marker}`,
102747
102950
  this.statusCallback?.();
102748
102951
  }
102749
102952
  maybeCaptureClaudeTuiPrompt() {
102750
- if (this.cliType !== "claude-cli" || this.activeInteractivePrompt || this.claudeTuiPromptCaptureInFlight) return;
102953
+ if (this.interactivePromptScheme() !== "claude_tui" || this.activeInteractivePrompt || this.claudeTuiPromptCaptureInFlight) return;
102751
102954
  const screenText = this.driver.snapshot();
102752
102955
  const headers = this.readClaudeTuiHeaders(screenText);
102753
102956
  if (!screenText.includes("Enter to select")) return;
@@ -102796,7 +102999,7 @@ ${marker}`,
102796
102999
  * eventually re-read and repaired.
102797
103000
  */
102798
103001
  maybeUpgradeClaudeTuiMultiSelect() {
102799
- if (this.cliType !== "claude-cli" || this.interactivePromptTransport !== "tui" || !this.activeInteractivePrompt) return;
103002
+ if (this.interactivePromptScheme() !== "claude_tui" || this.interactivePromptTransport !== "tui" || !this.activeInteractivePrompt) return;
102800
103003
  const questions = this.activeInteractivePrompt.questions;
102801
103004
  if (questions.every((q) => q.multiSelect)) return;
102802
103005
  let screenText = "";
@@ -104398,6 +104601,10 @@ ${buttons.join("\n")}`;
104398
104601
  const wedgedGeneratingProven = observedStatus === "generating" && isWedgedGeneratingWithNativeTurnEnd(host);
104399
104602
  if (observedStatus !== "idle" && !wedgedGeneratingProven) return false;
104400
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
+ }
104401
104608
  const taskId = host.completingTurnTaskId();
104402
104609
  if (host.shouldSuppressCompletionReEmit(taskId)) {
104403
104610
  return false;
@@ -104466,6 +104673,8 @@ ${buttons.join("\n")}`;
104466
104673
  const fastCollapsed = !!startedTurnTaskId && !host.hasAdapterPendingResponse() && !host.generatingStartedAt && !host.generatingDebouncePending;
104467
104674
  if (!fastCollapsed) return false;
104468
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;
104469
104678
  let fcFinalSummary;
104470
104679
  let fcEvidenceSource = "unavailable";
104471
104680
  try {
@@ -126232,7 +126441,12 @@ async (params) => {
126232
126441
  ctx.json(res, 503, { error: "InstanceManager not available" });
126233
126442
  return;
126234
126443
  }
126235
- 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);
126236
126450
  if (!target) {
126237
126451
  const allStates = ctx.instanceManager.collectAllStates();
126238
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) });