@adhdev/daemon-core 0.9.82-rc.137 → 0.9.82-rc.138

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 (39) hide show
  1. package/dist/chat/source-machine.d.ts +166 -0
  2. package/dist/chat/source-resolver.d.ts +104 -0
  3. package/dist/cli-adapters/cli-state-engine.d.ts +15 -0
  4. package/dist/cli-adapters/provider-cli-adapter.d.ts +0 -1
  5. package/dist/cli-adapters/provider-cli-parse.d.ts +1 -0
  6. package/dist/cli-adapters/provider-cli-shared.d.ts +1 -0
  7. package/dist/index.js +922 -328
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +922 -328
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/mesh/contracts.d.ts +164 -0
  12. package/dist/providers/contracts.d.ts +19 -0
  13. package/dist/providers/read-chat-contract.d.ts +29 -0
  14. package/dist/providers/transcript-v2.d.ts +176 -0
  15. package/dist/shared-types.d.ts +7 -0
  16. package/dist/status/snapshot.d.ts +1 -0
  17. package/dist/types.d.ts +5 -0
  18. package/package.json +1 -1
  19. package/src/chat/source-machine.ts +534 -0
  20. package/src/chat/source-resolver.ts +0 -0
  21. package/src/chat/subscription-updates.ts +9 -0
  22. package/src/cli-adapters/cli-state-engine.ts +103 -6
  23. package/src/cli-adapters/provider-cli-adapter.ts +51 -5
  24. package/src/cli-adapters/provider-cli-parse.ts +3 -0
  25. package/src/cli-adapters/provider-cli-shared.ts +13 -1
  26. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +17 -1
  27. package/src/cli-adapters/terminal-backends/xterm-backend.ts +8 -1
  28. package/src/commands/chat-commands.ts +712 -381
  29. package/src/commands/router.ts +14 -2
  30. package/src/config/chat-history.ts +36 -13
  31. package/src/mesh/contracts.ts +329 -0
  32. package/src/providers/contracts.ts +19 -0
  33. package/src/providers/provider-loader.ts +21 -7
  34. package/src/providers/provider-schema.ts +10 -0
  35. package/src/providers/read-chat-contract.ts +74 -14
  36. package/src/providers/transcript-v2.ts +567 -0
  37. package/src/shared-types.ts +7 -0
  38. package/src/status/snapshot.ts +35 -11
  39. package/src/types.ts +5 -0
package/dist/index.js CHANGED
@@ -4350,7 +4350,14 @@ var init_ghostty_vt_backend = __esm({
4350
4350
  this.terminal.write(data);
4351
4351
  }
4352
4352
  getText() {
4353
- return this.terminal.formatPlainText({ trim: true }) || "";
4353
+ const raw = this.terminal.formatPlainText({ trim: false }) || "";
4354
+ if (!raw) return "";
4355
+ const lines = raw.split("\n").map((row) => row.replace(/\s+$/, ""));
4356
+ let first = 0;
4357
+ let last = lines.length;
4358
+ while (first < last && !lines[first]) first += 1;
4359
+ while (last > first && !lines[last - 1]) last -= 1;
4360
+ return lines.slice(first, last).join("\n");
4354
4361
  }
4355
4362
  getCursorPosition() {
4356
4363
  return this.terminal.getCursorPosition();
@@ -4404,7 +4411,8 @@ var init_xterm_backend = __esm({
4404
4411
  const lines = [];
4405
4412
  for (let i = start; i < end; i++) {
4406
4413
  const line = buffer.getLine(i);
4407
- lines.push(line ? line.translateToString(true) : "");
4414
+ const raw = line ? line.translateToString(false) : "";
4415
+ lines.push(raw.replace(/\s+$/, ""));
4408
4416
  }
4409
4417
  let first = 0;
4410
4418
  let last = lines.length;
@@ -4936,8 +4944,13 @@ var init_provider_cli_shared = __esm({
4936
4944
  this.ensureRow();
4937
4945
  if (final === "A") this.row = Math.max(0, this.row - count);
4938
4946
  else if (final === "B") this.row += count;
4939
- else if (final === "C") this.col += count;
4940
- else if (final === "D") this.col = Math.max(0, this.col - count);
4947
+ else if (final === "C") {
4948
+ const line = this.lines[this.row];
4949
+ for (let c = this.col; c < this.col + count; c += 1) {
4950
+ if (line[c] === void 0) line[c] = " ";
4951
+ }
4952
+ this.col += count;
4953
+ } else if (final === "D") this.col = Math.max(0, this.col - count);
4941
4954
  else if (final === "G") this.col = Math.max(0, count - 1);
4942
4955
  else if (final === "H" || final === "f") {
4943
4956
  const parts = String(params || "").split(";");
@@ -5110,7 +5123,8 @@ function buildCliParseInput(options) {
5110
5123
  partialResponse,
5111
5124
  isWaitingForResponse,
5112
5125
  scope,
5113
- runtimeSettings
5126
+ runtimeSettings,
5127
+ spawnAt
5114
5128
  } = options;
5115
5129
  const buffer = scope ? sliceFromOffset(accumulatedBuffer, scope.bufferStart) : accumulatedBuffer;
5116
5130
  const rawBuffer = scope ? sliceFromOffset(accumulatedRawBuffer, scope.rawBufferStart) : accumulatedRawBuffer;
@@ -5132,7 +5146,8 @@ function buildCliParseInput(options) {
5132
5146
  partialResponse,
5133
5147
  isWaitingForResponse,
5134
5148
  promptText: scope?.prompt || "",
5135
- settings: { ...runtimeSettings }
5149
+ settings: { ...runtimeSettings },
5150
+ ...typeof spawnAt === "number" && spawnAt > 0 ? { spawnAt } : {}
5136
5151
  };
5137
5152
  }
5138
5153
  function summarizeCliTraceText(text, max = 800) {
@@ -5148,7 +5163,7 @@ var init_provider_cli_parse = __esm({
5148
5163
  });
5149
5164
 
5150
5165
  // src/cli-adapters/cli-state-engine.ts
5151
- var SCRIPT_STATUS_DEBOUNCE_MS, MAX_FINISH_RETRIES, FINISH_RETRY_DELAY_MS, MAX_TRACE_ENTRIES, APPROVAL_EXIT_TIMEOUT_MS, CliStateEngine;
5166
+ var SCRIPT_STATUS_DEBOUNCE_MS, MAX_FINISH_RETRIES, FINISH_RETRY_DELAY_MS, MAX_TRACE_ENTRIES, APPROVAL_EXIT_TIMEOUT_MS, IDLE_CONFIRMATION_GRACE_MS, CliStateEngine;
5152
5167
  var init_cli_state_engine = __esm({
5153
5168
  "src/cli-adapters/cli-state-engine.ts"() {
5154
5169
  "use strict";
@@ -5160,6 +5175,7 @@ var init_cli_state_engine = __esm({
5160
5175
  FINISH_RETRY_DELAY_MS = 300;
5161
5176
  MAX_TRACE_ENTRIES = 250;
5162
5177
  APPROVAL_EXIT_TIMEOUT_MS = 6e4;
5178
+ IDLE_CONFIRMATION_GRACE_MS = 2e3;
5163
5179
  CliStateEngine = class {
5164
5180
  constructor(provider, runner, transport, callbacks, timeouts) {
5165
5181
  this.provider = provider;
@@ -5198,6 +5214,20 @@ var init_cli_state_engine = __esm({
5198
5214
  pendingScriptStatusTimer = null;
5199
5215
  // ── Idle candidate ───────────────────────────────
5200
5216
  idleFinishCandidate = null;
5217
+ // ── Idle confirmation grace ──────────────────────
5218
+ /**
5219
+ * `finishResponse` produces the `generating → idle` transition that
5220
+ * coordinators interpret as "task complete". Some providers (antigravity-
5221
+ * cli observed in the wild) briefly paint a screen that looks like an
5222
+ * idle prompt between tool result frames while still actively running,
5223
+ * which fired `response_finished` and broke completion semantics.
5224
+ * We defer the actual idle transition by IDLE_CONFIRMATION_GRACE_MS and
5225
+ * cancel it if the scripted detection re-detects generating during that
5226
+ * window — a true completion stays idle for many seconds, so a 2-second
5227
+ * grace is sufficient to filter the paint blip.
5228
+ */
5229
+ pendingIdleFinishTimer = null;
5230
+ pendingIdleFinishAt = 0;
5201
5231
  // ── Status history (debug) ───────────────────────
5202
5232
  statusHistory = [];
5203
5233
  traceEntries = [];
@@ -5372,6 +5402,11 @@ var init_cli_state_engine = __esm({
5372
5402
  clearTimeout(this.providerErrorRetryTimer);
5373
5403
  this.providerErrorRetryTimer = null;
5374
5404
  }
5405
+ if (this.pendingIdleFinishTimer) {
5406
+ clearTimeout(this.pendingIdleFinishTimer);
5407
+ this.pendingIdleFinishTimer = null;
5408
+ this.pendingIdleFinishAt = 0;
5409
+ }
5375
5410
  this.providerErrorRetryKey = "";
5376
5411
  }
5377
5412
  resetActiveTurnState() {
@@ -5515,7 +5550,7 @@ var init_cli_state_engine = __esm({
5515
5550
  "CLI",
5516
5551
  `[${this.provider.type}] settled diagnostics prompt=${JSON.stringify(this.currentTurnScope?.prompt || "").slice(0, 140)} status=${String(status || "")} parsedStatus=${String(parsedStatus || "")} parsedMsgCount=${parsedMessages.length} lastParsedAssistant=${JSON.stringify((lastParsedAssistant?.content || "").slice(0, 120)).slice(0, 160)} responseBuffer=${JSON.stringify((snap.responseBuffer || "").slice(0, 160)).slice(0, 220)}`
5517
5552
  );
5518
- const shouldHoldGenerating = status === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(parsedStatus === "idle" && !!lastParsedAssistant);
5553
+ const shouldHoldGenerating = status === "idle" && this.isWaitingForResponse && !!this.currentTurnScope && !modal && recentInteractiveActivity && !(parsedStatus === "idle" && !!lastParsedAssistant);
5519
5554
  if (shouldHoldGenerating) {
5520
5555
  this.applyHoldGenerating(ctx);
5521
5556
  return;
@@ -5611,19 +5646,30 @@ var init_cli_state_engine = __esm({
5611
5646
  if (!inCooldown) {
5612
5647
  if (!modal) {
5613
5648
  LOG.warn("CLI", `[${this.provider.type}] detectStatus=waiting_approval but parseApproval returned null; ignoring`);
5649
+ if (this.currentStatus === "waiting_approval") {
5650
+ this.activeModal = null;
5651
+ this.setStatus("generating", "approval_lost_modal");
5652
+ this.callbacks.onStatusChange();
5653
+ }
5614
5654
  return;
5615
5655
  }
5616
5656
  this.isWaitingForResponse = true;
5617
5657
  this.setStatus("waiting_approval", "script_detect");
5618
- this.activeModal = modal;
5658
+ const prev = this.activeModal;
5659
+ const prevBtnCount = Array.isArray(prev?.buttons) ? prev.buttons.length : 0;
5660
+ const nextBtnCount = Array.isArray(modal.buttons) ? modal.buttons.length : 0;
5661
+ if (!prev || prevBtnCount !== nextBtnCount) {
5662
+ this.activeModal = modal;
5663
+ this.callbacks.onStatusChange();
5664
+ }
5619
5665
  if (this.idleTimeout) clearTimeout(this.idleTimeout);
5620
5666
  this.armApprovalExitTimeout();
5621
- this.callbacks.onStatusChange();
5622
5667
  }
5623
5668
  }
5624
5669
  applyGenerating(ctx) {
5625
5670
  const { modal, parsedMessages, lastParsedAssistant, parsedStatus, prevStatus } = ctx;
5626
5671
  this.clearIdleFinishCandidate("generating");
5672
+ this.cancelPendingIdleFinish("generating_signal_returned");
5627
5673
  const snap = this.transport.getSnapshot();
5628
5674
  const effectiveScreenText = snap.screenText || snap.accumulatedBuffer;
5629
5675
  const noActiveTurn = !this.currentTurnScope;
@@ -5784,10 +5830,27 @@ var init_cli_state_engine = __esm({
5784
5830
  }
5785
5831
  this.resetActiveTurnState();
5786
5832
  this.callbacks.onTurnCompleted();
5787
- this.setStatus("idle", "response_finished");
5788
- this.callbacks.onStatusChange();
5833
+ this.scheduleIdleFinish("response_finished");
5789
5834
  this.transport.flushOutboundQueue();
5790
5835
  }
5836
+ scheduleIdleFinish(reason) {
5837
+ if (this.pendingIdleFinishTimer) clearTimeout(this.pendingIdleFinishTimer);
5838
+ this.pendingIdleFinishAt = Date.now() + IDLE_CONFIRMATION_GRACE_MS;
5839
+ this.pendingIdleFinishTimer = setTimeout(() => {
5840
+ this.pendingIdleFinishTimer = null;
5841
+ this.pendingIdleFinishAt = 0;
5842
+ if (this.isWaitingForResponse) return;
5843
+ this.setStatus("idle", reason);
5844
+ this.callbacks.onStatusChange();
5845
+ }, IDLE_CONFIRMATION_GRACE_MS);
5846
+ }
5847
+ cancelPendingIdleFinish(reason) {
5848
+ if (!this.pendingIdleFinishTimer) return;
5849
+ clearTimeout(this.pendingIdleFinishTimer);
5850
+ this.pendingIdleFinishTimer = null;
5851
+ this.pendingIdleFinishAt = 0;
5852
+ this.recordTrace("idle_finish_cancelled", { trigger: reason });
5853
+ }
5791
5854
  // ─── Helpers ────────────────────────────────────────────────────────────
5792
5855
  armApprovalExitTimeout() {
5793
5856
  if (this.approvalExitTimeout) clearTimeout(this.approvalExitTimeout);
@@ -6224,9 +6287,10 @@ var init_provider_cli_adapter = __esm({
6224
6287
  submitRetryTimer = null;
6225
6288
  // Resize redraw suppression
6226
6289
  resizeSuppressUntil = 0;
6227
- // Native transcript anchor when >0, native history was confirmed for this session.
6228
- // Prevents freshEnough flips caused by PTY buffer activity after the first successful native read.
6229
- nativeHistoryAnchoredAt = 0;
6290
+ // (A2.2) Native transcript anchor moved to CHAT_SOURCE_REGISTRY.
6291
+ // ChatSourceMachine holds the lock by state, not by a mutable field on
6292
+ // the adapter. Removed entirely; no callers remain after the readChat
6293
+ // ladder was replaced.
6230
6294
  // ─── Script runner (parsing isolated here, adapter stays as transport) ───
6231
6295
  runner;
6232
6296
  /** @deprecated use runner.cliScripts for direct script access */
@@ -6562,6 +6626,8 @@ ${lastSnapshot}`;
6562
6626
  this.engine.lastApprovalResolvedAt = Date.now();
6563
6627
  }
6564
6628
  this.engine.activeModal = null;
6629
+ this.engine.isWaitingForResponse = false;
6630
+ this.engine.currentTurnScope = null;
6565
6631
  this.engine.setStatus("idle", `startup_ready:${trigger}`);
6566
6632
  }
6567
6633
  LOG.info(
@@ -6654,7 +6720,8 @@ ${lastSnapshot}`;
6654
6720
  partialResponse: this.responseBuffer,
6655
6721
  isWaitingForResponse: this.engine.isWaitingForResponse,
6656
6722
  scope: this.engine.currentTurnScope,
6657
- runtimeSettings: this.runtimeSettings
6723
+ runtimeSettings: this.runtimeSettings,
6724
+ spawnAt: this.spawnAt
6658
6725
  });
6659
6726
  const session = this.runner.parseSession({
6660
6727
  ...input,
@@ -6691,7 +6758,7 @@ ${lastSnapshot}`;
6691
6758
  }
6692
6759
  applyParsedSessionMetadata(parsed) {
6693
6760
  const providerSessionId = typeof parsed?.providerSessionId === "string" && parsed.providerSessionId.trim() ? parsed.providerSessionId.trim() : "";
6694
- if (providerSessionId) {
6761
+ if (providerSessionId && providerSessionId !== this.providerSessionId) {
6695
6762
  this.providerSessionId = providerSessionId;
6696
6763
  this.updateRuntimeMeta({ providerSessionId });
6697
6764
  }
@@ -6709,7 +6776,25 @@ ${lastSnapshot}`;
6709
6776
  const startupDetectedStatus = allowParse && this.startupParseGate && !startupModal ? this.runDetectStatus(this.recentOutputBuffer || this.terminalScreen.getText()) : null;
6710
6777
  let effectiveStatus = this.projectEffectiveStatus(startupModal);
6711
6778
  let effectiveModal = startupModal || this.engine.activeModal;
6712
- if (startupDetectedStatus === "waiting_approval") {
6779
+ if (allowParse && !effectiveModal && this.engine.isWaitingForResponse) {
6780
+ const liveDetect = this.runDetectStatus(this.recentOutputBuffer || this.terminalScreen.getText());
6781
+ if (liveDetect === "waiting_approval") {
6782
+ const liveModal = this.runParseApproval(this.terminalScreen.getText()) || this.runParseApproval(this.recentOutputBuffer);
6783
+ if (liveModal) {
6784
+ effectiveModal = liveModal;
6785
+ if (!this.engine.activeModal) this.engine.activeModal = liveModal;
6786
+ } else {
6787
+ LOG.warn("CLI", `[${this.cliType}] getStatus live re-extract: detect=waiting_approval but parseApproval still null (recentLen=${this.recentOutputBuffer.length} screenLen=${this.terminalScreen.getText().length})`);
6788
+ }
6789
+ } else if (liveDetect && liveDetect !== "generating" && liveDetect !== "idle") {
6790
+ LOG.warn("CLI", `[${this.cliType}] getStatus live re-extract: detect=${liveDetect} (not waiting_approval)`);
6791
+ } else if (this.engine.currentStatus === "waiting_approval" && liveDetect !== "waiting_approval") {
6792
+ LOG.warn("CLI", `[${this.cliType}] getStatus live re-extract: engine.status=waiting_approval but live detect=${liveDetect}`);
6793
+ }
6794
+ } else if (!effectiveModal && this.engine.currentStatus === "waiting_approval") {
6795
+ LOG.warn("CLI", `[${this.cliType}] getStatus skipped live re-extract: allowParse=${allowParse} isWaitingForResponse=${this.engine.isWaitingForResponse}`);
6796
+ }
6797
+ if (startupDetectedStatus === "waiting_approval" && effectiveModal) {
6713
6798
  effectiveStatus = "waiting_approval";
6714
6799
  } else if (startupDetectedStatus === "idle" && !startupModal && !effectiveModal) {
6715
6800
  effectiveStatus = "idle";
@@ -6811,7 +6896,8 @@ ${lastSnapshot}`;
6811
6896
  partialResponse: this.responseBuffer,
6812
6897
  isWaitingForResponse: this.engine.isWaitingForResponse,
6813
6898
  scope: this.engine.currentTurnScope,
6814
- runtimeSettings: this.runtimeSettings
6899
+ runtimeSettings: this.runtimeSettings,
6900
+ spawnAt: this.spawnAt
6815
6901
  });
6816
6902
  return await Promise.resolve(this.runner.invokeByName(scriptName, {
6817
6903
  ...input,
@@ -14848,19 +14934,37 @@ function getProviderNativeHistoryScript(scripts, canonicalHistory, key) {
14848
14934
  function normalizeProviderNativeHistoryRecords(agentType, historySessionId, records) {
14849
14935
  if (!Array.isArray(records)) return [];
14850
14936
  const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
14851
- return records.map((record) => sanitizeHistoryMessage(agentType, {
14852
- ts: typeof record?.ts === "string" ? record.ts : new Date(Number(record?.receivedAt) || Date.now()).toISOString(),
14853
- receivedAt: Number(record?.receivedAt) || Date.parse(record?.ts || "") || Date.now(),
14854
- role: record?.role,
14855
- content: String(record?.content || ""),
14856
- kind: record?.kind || (record?.role === "system" ? "session_start" : "standard"),
14857
- senderName: record?.senderName,
14858
- agent: agentType,
14859
- instanceId: record?.instanceId,
14860
- historySessionId: normalizeSavedHistorySessionId(record?.historySessionId || normalizedSessionId),
14861
- sessionTitle: record?.sessionTitle,
14862
- workspace: record?.workspace
14863
- })).filter(Boolean);
14937
+ return records.map((record) => {
14938
+ const base = {
14939
+ ts: typeof record?.ts === "string" ? record.ts : new Date(Number(record?.receivedAt) || Date.now()).toISOString(),
14940
+ receivedAt: Number(record?.receivedAt) || Date.parse(record?.ts || "") || Date.now(),
14941
+ role: record?.role,
14942
+ content: String(record?.content || ""),
14943
+ kind: record?.kind || (record?.role === "system" ? "session_start" : "standard"),
14944
+ senderName: record?.senderName,
14945
+ agent: agentType,
14946
+ instanceId: record?.instanceId,
14947
+ historySessionId: normalizeSavedHistorySessionId(record?.historySessionId || normalizedSessionId),
14948
+ sessionTitle: record?.sessionTitle,
14949
+ workspace: record?.workspace
14950
+ };
14951
+ if (typeof record?.providerUnitKey === "string" && record.providerUnitKey) {
14952
+ base.providerUnitKey = record.providerUnitKey;
14953
+ }
14954
+ if (typeof record?.bubbleId === "string" && record.bubbleId) {
14955
+ base.bubbleId = record.bubbleId;
14956
+ }
14957
+ if (typeof record?.sequence === "number" && Number.isFinite(record.sequence)) {
14958
+ base.sequence = record.sequence;
14959
+ }
14960
+ if (typeof record?._turnKey === "string" && record._turnKey) {
14961
+ base._turnKey = record._turnKey;
14962
+ }
14963
+ if (typeof record?.bubbleState === "string" && record.bubbleState) {
14964
+ base.bubbleState = record.bubbleState;
14965
+ }
14966
+ return sanitizeHistoryMessage(agentType, base);
14967
+ }).filter(Boolean);
14864
14968
  }
14865
14969
  function callProviderNativeHistoryRead(agentType, canonicalHistory, scripts, historySessionId, workspace, excludeInProgressTurn) {
14866
14970
  const fn = getProviderNativeHistoryScript(scripts, canonicalHistory, "readSession");
@@ -15525,6 +15629,9 @@ ${effect.notification.body || ""}`.trim();
15525
15629
  // src/providers/ide-provider-instance.ts
15526
15630
  init_logger();
15527
15631
 
15632
+ // src/providers/transcript-v2.ts
15633
+ var CHAT_CONTRACT_VERSION_V1 = "1.0";
15634
+
15528
15635
  // src/providers/read-chat-contract.ts
15529
15636
  var VALID_STATUSES = ["idle", "generating", "waiting_approval", "error", "panel_hidden", "starting", "streaming", "long_generating"];
15530
15637
  var VALID_ROLES = ["user", "assistant", "system", "human"];
@@ -15581,6 +15688,7 @@ function validateMessage(message, source, index) {
15581
15688
  if (isFiniteNumber(message.index)) normalized.index = message.index;
15582
15689
  if (isFiniteNumber(message.timestamp)) normalized.timestamp = message.timestamp;
15583
15690
  if (isFiniteNumber(message.receivedAt)) normalized.receivedAt = message.receivedAt;
15691
+ if (isFiniteNumber(message.sequence)) normalized.sequence = message.sequence;
15584
15692
  if (typeof message._turnKey === "string") normalized._turnKey = message._turnKey;
15585
15693
  if (Array.isArray(message.toolCalls)) normalized.toolCalls = message.toolCalls;
15586
15694
  if (isPlainObject3(message.meta)) normalized.meta = message.meta;
@@ -17512,12 +17620,365 @@ function buildSessionModalDeliverySignature(payload) {
17512
17620
  ]);
17513
17621
  }
17514
17622
 
17623
+ // src/chat/source-machine.ts
17624
+ var INITIAL_CHAT_SOURCE_STATE = Object.freeze({
17625
+ name: "Booting",
17626
+ nativeSequencePeak: void 0,
17627
+ committedUnitKeys: Object.freeze(/* @__PURE__ */ new Set()),
17628
+ recoveringMisses: 0
17629
+ });
17630
+ var RECOVERING_MISS_PROMOTION_THRESHOLD = 3;
17631
+ function transitionChatSourceState(prev, observation, at, lockedSince) {
17632
+ const fromState = prev.name;
17633
+ if (observation.kind === "native_unavailable") {
17634
+ return handleNativeUnavailable(prev, observation.reason, at, lockedSince);
17635
+ }
17636
+ return handleNativePresent(prev, observation, at, lockedSince, fromState);
17637
+ }
17638
+ function handleNativeUnavailable(prev, reason, at, lockedSince) {
17639
+ const cause = reasonToUnavailableCause(reason);
17640
+ const fromState = prev.name;
17641
+ if (prev.name === "Booting") {
17642
+ const next2 = {
17643
+ name: "PtyOnly",
17644
+ nativeSequencePeak: void 0,
17645
+ committedUnitKeys: prev.committedUnitKeys,
17646
+ recoveringMisses: 0
17647
+ };
17648
+ return {
17649
+ next: next2,
17650
+ selected: "pty-parser",
17651
+ transition: { fromState, toState: "PtyOnly", event: "NativeUnavailable", cause, at },
17652
+ lockState: { locked: false }
17653
+ };
17654
+ }
17655
+ if (prev.name === "PtyOnly") {
17656
+ return {
17657
+ next: prev,
17658
+ selected: "pty-parser",
17659
+ transition: { fromState, toState: "PtyOnly", event: "NoOp", cause, at },
17660
+ lockState: { locked: false }
17661
+ };
17662
+ }
17663
+ if (prev.name === "NativeLocked") {
17664
+ const next2 = {
17665
+ name: "Recovering",
17666
+ nativeSequencePeak: prev.nativeSequencePeak,
17667
+ committedUnitKeys: prev.committedUnitKeys,
17668
+ recoveringMisses: 1
17669
+ };
17670
+ return {
17671
+ next: next2,
17672
+ selected: "pty-parser",
17673
+ transition: { fromState, toState: "Recovering", event: "NativeUnavailable", cause, at },
17674
+ lockState: { locked: false }
17675
+ };
17676
+ }
17677
+ const misses = prev.recoveringMisses + 1;
17678
+ if (misses >= RECOVERING_MISS_PROMOTION_THRESHOLD) {
17679
+ const next2 = {
17680
+ name: "PtyOnly",
17681
+ nativeSequencePeak: prev.nativeSequencePeak,
17682
+ committedUnitKeys: prev.committedUnitKeys,
17683
+ recoveringMisses: 0
17684
+ };
17685
+ return {
17686
+ next: next2,
17687
+ selected: "pty-parser",
17688
+ transition: { fromState, toState: "PtyOnly", event: "NativeUnavailable", cause, at },
17689
+ lockState: { locked: false }
17690
+ };
17691
+ }
17692
+ const next = {
17693
+ name: "Recovering",
17694
+ nativeSequencePeak: prev.nativeSequencePeak,
17695
+ committedUnitKeys: prev.committedUnitKeys,
17696
+ recoveringMisses: misses
17697
+ };
17698
+ return {
17699
+ next,
17700
+ selected: "pty-parser",
17701
+ transition: { fromState, toState: "Recovering", event: "NoOp", cause, at },
17702
+ lockState: { locked: false }
17703
+ };
17704
+ }
17705
+ function handleNativePresent(prev, observation, at, lockedSince, fromState) {
17706
+ if (!observation.safeMapping) {
17707
+ return regressTo(prev, fromState, "native_regressed_unsafe_mapping", at);
17708
+ }
17709
+ if (observation.coverage === "partial" && observation.messages.length === 0) {
17710
+ return regressTo(prev, fromState, "native_regressed_coverage_partial", at);
17711
+ }
17712
+ if (observation.messages.length === 0) {
17713
+ return handleNativeUnavailable(prev, "empty", at, lockedSince);
17714
+ }
17715
+ const incomingUnitKeys = collectUnitKeys(observation.messages);
17716
+ const incomingPeak = maxSequence(observation.messages);
17717
+ if (prev.name === "Booting") {
17718
+ if (observation.coverage === "partial") {
17719
+ const next2 = {
17720
+ name: "Recovering",
17721
+ nativeSequencePeak: incomingPeak,
17722
+ committedUnitKeys: incomingUnitKeys,
17723
+ recoveringMisses: 0
17724
+ };
17725
+ return {
17726
+ next: next2,
17727
+ selected: "pty-parser",
17728
+ transition: { fromState, toState: "Recovering", event: "NativeProgressed", cause: "native_progressed", at },
17729
+ lockState: { locked: false }
17730
+ };
17731
+ }
17732
+ const next = {
17733
+ name: "NativeLocked",
17734
+ nativeSequencePeak: incomingPeak,
17735
+ committedUnitKeys: incomingUnitKeys,
17736
+ recoveringMisses: 0
17737
+ };
17738
+ return {
17739
+ next,
17740
+ selected: "native-history",
17741
+ transition: { fromState, toState: "NativeLocked", event: "NativeProgressed", cause: "native_progressed", at },
17742
+ lockState: { locked: true, lockedSince: at }
17743
+ };
17744
+ }
17745
+ if (prev.name === "NativeLocked") {
17746
+ if (!isSupersetOf(incomingUnitKeys, prev.committedUnitKeys)) {
17747
+ return regressTo(prev, fromState, "native_regressed_shrunk", at);
17748
+ }
17749
+ if (prev.nativeSequencePeak !== void 0 && incomingPeak < prev.nativeSequencePeak) {
17750
+ return regressTo(prev, fromState, "native_regressed_shrunk", at);
17751
+ }
17752
+ const next = {
17753
+ name: "NativeLocked",
17754
+ nativeSequencePeak: Math.max(prev.nativeSequencePeak ?? incomingPeak, incomingPeak),
17755
+ committedUnitKeys: incomingUnitKeys,
17756
+ recoveringMisses: 0
17757
+ };
17758
+ return {
17759
+ next,
17760
+ selected: "native-history",
17761
+ transition: { fromState, toState: "NativeLocked", event: "NoOp", cause: "native_progressed", at },
17762
+ lockState: { locked: true, lockedSince: lockedSince ?? at }
17763
+ };
17764
+ }
17765
+ if (prev.name === "Recovering") {
17766
+ const meetsWatermark = prev.nativeSequencePeak === void 0 || incomingPeak >= prev.nativeSequencePeak;
17767
+ if (meetsWatermark && isSupersetOf(incomingUnitKeys, prev.committedUnitKeys) && observation.coverage !== "partial") {
17768
+ const next = {
17769
+ name: "NativeLocked",
17770
+ nativeSequencePeak: Math.max(prev.nativeSequencePeak ?? incomingPeak, incomingPeak),
17771
+ committedUnitKeys: incomingUnitKeys,
17772
+ recoveringMisses: 0
17773
+ };
17774
+ return {
17775
+ next,
17776
+ selected: "native-history",
17777
+ transition: { fromState, toState: "NativeLocked", event: "NativeProgressed", cause: "native_progressed", at },
17778
+ lockState: { locked: true, lockedSince: at }
17779
+ };
17780
+ }
17781
+ return handleNativeUnavailable(prev, "empty", at, lockedSince);
17782
+ }
17783
+ if (prev.nativeSequencePeak === void 0 || incomingPeak > prev.nativeSequencePeak) {
17784
+ if (observation.coverage !== "partial" && incomingUnitKeys.size > 0) {
17785
+ const next = {
17786
+ name: "NativeLocked",
17787
+ nativeSequencePeak: Math.max(prev.nativeSequencePeak ?? incomingPeak, incomingPeak),
17788
+ committedUnitKeys: incomingUnitKeys,
17789
+ recoveringMisses: 0
17790
+ };
17791
+ return {
17792
+ next,
17793
+ selected: "native-history",
17794
+ transition: { fromState, toState: "NativeLocked", event: "NativeProgressed", cause: "native_progressed", at },
17795
+ lockState: { locked: true, lockedSince: at }
17796
+ };
17797
+ }
17798
+ } else if (incomingPeak >= prev.nativeSequencePeak) {
17799
+ if (isSupersetOf(incomingUnitKeys, prev.committedUnitKeys) && observation.coverage !== "partial") {
17800
+ const next = {
17801
+ name: "NativeLocked",
17802
+ nativeSequencePeak: Math.max(prev.nativeSequencePeak ?? incomingPeak, incomingPeak),
17803
+ committedUnitKeys: incomingUnitKeys,
17804
+ recoveringMisses: 0
17805
+ };
17806
+ return {
17807
+ next,
17808
+ selected: "native-history",
17809
+ transition: { fromState, toState: "NativeLocked", event: "NativeProgressed", cause: "native_progressed", at },
17810
+ lockState: { locked: true, lockedSince: at }
17811
+ };
17812
+ }
17813
+ }
17814
+ return {
17815
+ next: prev,
17816
+ selected: "pty-parser",
17817
+ transition: { fromState, toState: "PtyOnly", event: "NoOp", cause: "native_progressed", at },
17818
+ lockState: { locked: false }
17819
+ };
17820
+ }
17821
+ function regressTo(prev, fromState, cause, at) {
17822
+ const next = {
17823
+ name: "PtyOnly",
17824
+ nativeSequencePeak: prev.nativeSequencePeak,
17825
+ committedUnitKeys: prev.committedUnitKeys,
17826
+ recoveringMisses: 0
17827
+ };
17828
+ return {
17829
+ next,
17830
+ selected: "pty-parser",
17831
+ transition: { fromState, toState: "PtyOnly", event: "NativeRegressed", cause, at },
17832
+ lockState: { locked: false }
17833
+ };
17834
+ }
17835
+ function reasonToUnavailableCause(reason) {
17836
+ switch (reason) {
17837
+ case "provider_not_supported":
17838
+ return "native_unavailable_provider_unsupported";
17839
+ case "read_error":
17840
+ return "native_unavailable_read_error";
17841
+ case "empty":
17842
+ return "native_unavailable_empty";
17843
+ case "not_native_source":
17844
+ return "native_unavailable_not_native_source";
17845
+ case "coverage_unavailable":
17846
+ return "native_regressed_coverage_unavailable";
17847
+ }
17848
+ }
17849
+ function collectUnitKeys(messages) {
17850
+ const set = /* @__PURE__ */ new Set();
17851
+ for (const m of messages) set.add(m.providerUnitKey);
17852
+ return set;
17853
+ }
17854
+ function maxSequence(messages) {
17855
+ let max = -Infinity;
17856
+ for (const m of messages) {
17857
+ if (m.sequence > max) max = m.sequence;
17858
+ }
17859
+ return max === -Infinity ? 0 : max;
17860
+ }
17861
+ function isSupersetOf(candidate, required) {
17862
+ if (required.size === 0) return true;
17863
+ for (const key of required) {
17864
+ if (!candidate.has(key)) return false;
17865
+ }
17866
+ return true;
17867
+ }
17868
+
17869
+ // src/chat/source-resolver.ts
17870
+ var TRANSITION_HISTORY_LIMIT = 25;
17871
+ function chatSourceSessionKey(providerType, sessionId) {
17872
+ return `${providerType}\0${sessionId}`;
17873
+ }
17874
+ var ChatSourceRegistry = class {
17875
+ records = /* @__PURE__ */ new Map();
17876
+ /** Snapshot of current state for diagnostics. Does not mutate. */
17877
+ getState(key) {
17878
+ return this.records.get(key)?.state ?? INITIAL_CHAT_SOURCE_STATE;
17879
+ }
17880
+ /** Recent transitions, newest last. Empty array when nothing has happened. */
17881
+ getTransitions(key) {
17882
+ return this.records.get(key)?.transitions ?? [];
17883
+ }
17884
+ /** Drop a session. Caller should invoke this when the session is destroyed
17885
+ * to avoid unbounded growth across long-lived daemons. */
17886
+ clear(key) {
17887
+ this.records.delete(key);
17888
+ }
17889
+ /** Drop all sessions. Test helper. */
17890
+ clearAll() {
17891
+ this.records.clear();
17892
+ }
17893
+ /**
17894
+ * Apply one observation, returning the decision and side-effecting the
17895
+ * stored state. The returned `nextState` is the same object now stored
17896
+ * under `key`; callers may treat the decision as authoritative without
17897
+ * re-reading.
17898
+ */
17899
+ observe(key, observation, at = Date.now()) {
17900
+ const prev = this.records.get(key);
17901
+ const prevState = prev?.state ?? INITIAL_CHAT_SOURCE_STATE;
17902
+ const prevLockedSince = prev?.lockedSince;
17903
+ const result = transitionChatSourceState(prevState, observation, at, prevLockedSince);
17904
+ const transitions = prev?.transitions ?? [];
17905
+ const nextTransitions = appendTransition(transitions, result.transition);
17906
+ const lockedSince = result.lockState.lockedSince;
17907
+ this.records.set(key, {
17908
+ state: result.next,
17909
+ lockedSince,
17910
+ transitions: nextTransitions
17911
+ });
17912
+ return {
17913
+ selected: result.selected,
17914
+ nextState: result.next,
17915
+ transition: result.transition,
17916
+ lockState: result.lockState
17917
+ };
17918
+ }
17919
+ };
17920
+ function appendTransition(existing, next) {
17921
+ const last = existing[existing.length - 1];
17922
+ if (last && last.fromState === next.fromState && last.toState === next.toState && last.event === next.event && last.cause === next.cause) {
17923
+ return existing;
17924
+ }
17925
+ const trimmed = existing.length >= TRANSITION_HISTORY_LIMIT ? existing.slice(existing.length - TRANSITION_HISTORY_LIMIT + 1) : [...existing];
17926
+ trimmed.push(next);
17927
+ return trimmed;
17928
+ }
17929
+ function buildV1NativePresentObservation(args) {
17930
+ const identities = [];
17931
+ let synthesisedSequence = 0;
17932
+ for (const message of args.messages) {
17933
+ const providerUnitKey = pickFirstString(
17934
+ message.providerUnitKey,
17935
+ message.bubbleId,
17936
+ message.id
17937
+ ) ?? synthesiseV1UnitKey(args.providerType, args.sessionId, synthesisedSequence, message);
17938
+ const sequence = pickFiniteNumber(message.receivedAt, message.timestamp, message.index) ?? synthesisedSequence;
17939
+ identities.push({ providerUnitKey, sequence });
17940
+ synthesisedSequence += 1;
17941
+ }
17942
+ return {
17943
+ kind: "native_present",
17944
+ contractVersion: CHAT_CONTRACT_VERSION_V1,
17945
+ messages: identities,
17946
+ coverage: args.coverage,
17947
+ safeMapping: args.safeMapping
17948
+ };
17949
+ }
17950
+ function pickFirstString(...candidates) {
17951
+ for (const c of candidates) {
17952
+ if (typeof c === "string" && c.length > 0) return c;
17953
+ }
17954
+ return void 0;
17955
+ }
17956
+ function pickFiniteNumber(...candidates) {
17957
+ for (const c of candidates) {
17958
+ if (typeof c === "number" && Number.isFinite(c)) return c;
17959
+ }
17960
+ return void 0;
17961
+ }
17962
+ function synthesiseV1UnitKey(providerType, sessionId, positionalSeq, message) {
17963
+ const role = typeof message.role === "string" ? message.role : "";
17964
+ const ts2 = pickFiniteNumber(message.receivedAt, message.timestamp);
17965
+ return `v1:${providerType}:${sessionId}:${ts2 ?? ""}:${positionalSeq}:${role}`;
17966
+ }
17967
+ var CHAT_SOURCE_REGISTRY = new ChatSourceRegistry();
17968
+
17515
17969
  // src/commands/chat-commands.ts
17516
17970
  var RECENT_SEND_WINDOW_MS = 1200;
17517
17971
  var READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25e3;
17518
17972
  var HERMES_CLI_STARTING_SEND_SETTLE_MS = 2e3;
17519
- var CLI_NATIVE_HISTORY_FRESH_MS = 5 * 6e4;
17520
17973
  var CLI_NATIVE_TRANSCRIPT_PROVIDERS = /* @__PURE__ */ new Set(["codex-cli", "claude-cli", "hermes-cli", "antigravity-cli"]);
17974
+ var warnedLegacyNativeAllowlistHits = /* @__PURE__ */ new Set();
17975
+ function warnLegacyNativeAllowlistHit(providerType) {
17976
+ if (warnedLegacyNativeAllowlistHits.has(providerType)) return;
17977
+ warnedLegacyNativeAllowlistHits.add(providerType);
17978
+ console.warn(
17979
+ `[chat-commands] supportsCliNativeTranscript fell back to the hardcoded CLI_NATIVE_TRANSCRIPT_PROVIDERS set for "${providerType}". The provider module was unavailable or did not declare canonicalHistory. Set canonicalHistory.contractVersion in the provider.json to remove this dependency.`
17980
+ );
17981
+ }
17521
17982
  var recentSendByTarget = /* @__PURE__ */ new Map();
17522
17983
  function getCurrentProviderType(h, fallback = "") {
17523
17984
  return h.currentSession?.providerType || h.currentProviderType || fallback;
@@ -17692,7 +18153,11 @@ function readHistorySessionIdFromMessages(messages) {
17692
18153
  function shouldPreserveNativeIdentity(providerType, sessionId, message) {
17693
18154
  const providerUnitKey = typeof message.providerUnitKey === "string" ? message.providerUnitKey.trim() : "";
17694
18155
  const turnKey = typeof message._turnKey === "string" ? message._turnKey.trim() : "";
17695
- if (!providerUnitKey || !turnKey) return false;
18156
+ if (!providerUnitKey) return false;
18157
+ if (providerUnitKey.startsWith("v2:") || providerUnitKey.startsWith("v2-pty:")) {
18158
+ return true;
18159
+ }
18160
+ if (!turnKey) return false;
17696
18161
  if (providerType === "hermes-cli" && sessionId) {
17697
18162
  return providerUnitKey.startsWith(`${providerType}:native:${sessionId}:`) && turnKey.startsWith(`${providerType}:native-turn:${sessionId}:`);
17698
18163
  }
@@ -17721,12 +18186,16 @@ function normalizeNativeHistoryMessages(providerType, messages, nativeSessionId)
17721
18186
  const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
17722
18187
  const isSystemSessionStart = role === "system" || kind === "system" || kind === "session_start";
17723
18188
  const isActivity = role === "assistant" && (kind === "tool" || kind === "terminal" || kind === "thought");
18189
+ const existingSequence = typeof message.sequence === "number" && Number.isFinite(message.sequence) ? message.sequence : null;
18190
+ const tsCandidate = Number(message.receivedAt || message.timestamp || 0);
18191
+ const sequence = existingSequence !== null ? existingSequence : tsCandidate > 0 ? tsCandidate : index;
17724
18192
  return {
17725
18193
  ...message,
17726
18194
  role: role === "human" ? "user" : role || "assistant",
17727
18195
  kind: isSystemSessionStart ? "system" : kind,
17728
18196
  providerUnitKey,
17729
18197
  bubbleId: typeof message.bubbleId === "string" && message.bubbleId.trim() && preserveNativeIdentity ? message.bubbleId.trim() : `bubble:${providerUnitKey}`,
18198
+ sequence,
17730
18199
  _turnKey: preserveNativeIdentity ? existingTurnKey : `${providerType}:native-turn:${nativeIdentitySessionId || "workspace"}:${turnIndex}`,
17731
18200
  bubbleState: message.bubbleState || "final",
17732
18201
  ...isSystemSessionStart ? {
@@ -17785,17 +18254,185 @@ function buildCliMessageSourceProvenance(args) {
17785
18254
  }
17786
18255
  };
17787
18256
  }
17788
- function buildNativeHistoryFallbackReason(args) {
17789
- if (!supportsCliNativeTranscript(args.providerType, args.provider)) return "provider_native_transcript_not_supported";
17790
- if (args.unavailableReason) return `native_history_unavailable:${args.unavailableReason}`;
17791
- if (args.nativeSource === "native-unavailable") return "native_history_unavailable";
17792
- if (args.nativeHistoryCoverage === "partial") return "native_history_partial";
17793
- if (args.nativeHistoryCoverage === "unavailable") return "native_history_unavailable";
17794
- if (args.nativeSource && args.nativeSource !== "provider-native") return `native_history_source_${args.nativeSource}`;
17795
- if (args.nativeMessageCount <= 0) return "native_history_empty";
17796
- if (!args.safeMapping) return "native_history_not_safely_mapped";
17797
- if (!args.freshEnough) return "native_history_stale";
17798
- return "native_history_not_selected";
18257
+ function causeToLegacyFallbackReason(cause, selected, extraDetail) {
18258
+ if (selected === "native-history") return void 0;
18259
+ switch (cause) {
18260
+ case "initial":
18261
+ return "native_history_not_checked";
18262
+ case "native_progressed":
18263
+ return "native_history_not_selected";
18264
+ case "native_regressed_shrunk":
18265
+ return "native_history_empty";
18266
+ case "native_regressed_unsafe_mapping":
18267
+ return "native_history_not_safely_mapped";
18268
+ case "native_regressed_coverage_partial":
18269
+ return "native_history_partial";
18270
+ case "native_regressed_coverage_unavailable":
18271
+ return "native_history_unavailable";
18272
+ case "native_unavailable_read_error":
18273
+ return extraDetail?.unavailableReason ? `native_history_unavailable:${extraDetail.unavailableReason}` : "native_history_unavailable";
18274
+ case "native_unavailable_provider_unsupported":
18275
+ return "provider_native_transcript_not_supported";
18276
+ case "native_unavailable_empty":
18277
+ return "native_history_empty";
18278
+ case "native_unavailable_not_native_source":
18279
+ return extraDetail?.nativeSource ? `native_history_source_${extraDetail.nativeSource}` : "native_history_unavailable";
18280
+ }
18281
+ }
18282
+ function decideCliReadChatSource(args) {
18283
+ const supportsNative = supportsCliNativeTranscript(args.providerType, args.provider);
18284
+ const observation = buildObservationForCli(args, supportsNative);
18285
+ const sessionKey = chatSourceSessionKey(args.providerType, args.sessionId);
18286
+ const decision = CHAT_SOURCE_REGISTRY.observe(sessionKey, observation);
18287
+ const nativeMessages = observation.kind === "native_present" ? extractNativeMessagesFromResult(args.providerType, args.nativeHistoryResult) : [];
18288
+ const nativeSource = typeof args.nativeHistoryResult?.source === "string" ? args.nativeHistoryResult.source : void 0;
18289
+ const sourcePath = typeof args.nativeHistoryResult?.sourcePath === "string" ? args.nativeHistoryResult.sourcePath : void 0;
18290
+ const sourceMtimeMs = typeof args.nativeHistoryResult?.sourceMtimeMs === "number" ? args.nativeHistoryResult.sourceMtimeMs : void 0;
18291
+ const coverageHint = typeof args.nativeHistoryResult?.nativeHistoryCoverage === "string" ? args.nativeHistoryResult.nativeHistoryCoverage : void 0;
18292
+ const partialReason = typeof args.nativeHistoryResult?.partialReason === "string" ? args.nativeHistoryResult.partialReason : void 0;
18293
+ const unavailableReason = typeof args.nativeHistoryResult?.unavailableReason === "string" ? args.nativeHistoryResult.unavailableReason : args.nativeHistoryError ? `error:${args.nativeHistoryError?.message || String(args.nativeHistoryError)}` : void 0;
18294
+ const nativeHandle = typeof args.nativeHistoryResult?.providerSessionId === "string" ? args.nativeHistoryResult.providerSessionId : void 0;
18295
+ const transcriptWorkspace = typeof args.nativeHistoryResult?.workspace === "string" ? args.nativeHistoryResult.workspace : nativeMessages.map((m) => typeof m?.workspace === "string" ? m.workspace.trim() : "").find(Boolean);
18296
+ const fallbackReason = causeToLegacyFallbackReason(decision.transition.cause, decision.selected, {
18297
+ unavailableReason,
18298
+ nativeSource: nativeSource && nativeSource !== "provider-native" ? nativeSource : void 0
18299
+ });
18300
+ const ptyStatusApprovalOnly = decision.selected === "native-history" ? true : args.ptyStatusApprovalOnly;
18301
+ const messageSource = buildCliMessageSourceProvenance({
18302
+ selected: decision.selected,
18303
+ provider: args.providerType,
18304
+ nativeHandle,
18305
+ sessionWorkspace: args.sessionWorkspace,
18306
+ intendedWorkspace: args.intendedWorkspace,
18307
+ transcriptWorkspace,
18308
+ fallbackReason,
18309
+ nativeSource,
18310
+ sourcePath,
18311
+ sourceMtimeMs,
18312
+ nativeHistoryCoverage: coverageHint,
18313
+ partialReason,
18314
+ unavailableReason,
18315
+ nativeMessages,
18316
+ ptyMessages: args.ptyMessages,
18317
+ returnedMessages: decision.selected === "native-history" ? nativeMessages : args.ptyMessages,
18318
+ safeMapping: args.safeMapping,
18319
+ // freshEnough is a v1 concept the machine does not model directly.
18320
+ // We surface lockState.locked here so v1 consumers reading
18321
+ // staleness.freshEnough still get a meaningful boolean.
18322
+ freshEnough: decision.lockState.locked,
18323
+ ptyStatusApprovalOnly
18324
+ });
18325
+ return {
18326
+ decision,
18327
+ messageSource,
18328
+ nativeMessages,
18329
+ nativeSelected: decision.selected === "native-history"
18330
+ };
18331
+ }
18332
+ function buildObservationForCli(args, supportsNative) {
18333
+ if (!supportsNative) {
18334
+ return { kind: "native_unavailable", reason: "provider_not_supported" };
18335
+ }
18336
+ if (args.nativeHistoryError) {
18337
+ return { kind: "native_unavailable", reason: "read_error" };
18338
+ }
18339
+ const result = args.nativeHistoryResult;
18340
+ if (!result || typeof result !== "object") {
18341
+ return { kind: "native_unavailable", reason: "read_error" };
18342
+ }
18343
+ const source = typeof result.source === "string" ? result.source : "";
18344
+ if (source && source !== "provider-native") {
18345
+ return { kind: "native_unavailable", reason: source === "native-unavailable" ? "empty" : "not_native_source" };
18346
+ }
18347
+ const messages = Array.isArray(result.messages) ? result.messages : [];
18348
+ if (messages.length === 0) {
18349
+ return { kind: "native_unavailable", reason: "empty" };
18350
+ }
18351
+ const coverage = typeof result.nativeHistoryCoverage === "string" ? result.nativeHistoryCoverage : "tail";
18352
+ if (coverage === "unavailable") {
18353
+ return { kind: "native_unavailable", reason: "coverage_unavailable" };
18354
+ }
18355
+ return buildV1NativePresentObservation({
18356
+ providerType: args.providerType,
18357
+ sessionId: args.sessionId,
18358
+ messages,
18359
+ coverage: coverage === "full" || coverage === "tail" || coverage === "current-turn" || coverage === "partial" ? coverage : "tail",
18360
+ safeMapping: args.safeMapping
18361
+ });
18362
+ }
18363
+ function extractNativeMessagesFromResult(providerType, result) {
18364
+ if (!result || !Array.isArray(result.messages)) return [];
18365
+ return normalizeNativeHistoryMessages(
18366
+ providerType,
18367
+ result.messages,
18368
+ typeof result.providerSessionId === "string" ? result.providerSessionId : void 0
18369
+ );
18370
+ }
18371
+ function applyUnsafeNativeDaemonFallback(args) {
18372
+ if (args.adapter.cliType !== "codex-cli") {
18373
+ return;
18374
+ }
18375
+ const ms = args.messageSourceRef.get();
18376
+ const fallbackReason = typeof ms.fallbackReason === "string" ? ms.fallbackReason : "";
18377
+ if (!isUnsafeNativeTranscriptFallback(fallbackReason)) {
18378
+ return;
18379
+ }
18380
+ const safeCurrentRuntimePtyMessages = isCurrentRuntimePtySafelyAttributed({
18381
+ adapter: args.adapter,
18382
+ helpers: args.helpers,
18383
+ readChatArgs: args.readChatArgs,
18384
+ sessionWorkspace: args.sessionWorkspace,
18385
+ intendedWorkspace: args.intendedWorkspace,
18386
+ ptyMessages: args.ptyMessages
18387
+ });
18388
+ if (safeCurrentRuntimePtyMessages) {
18389
+ args.apply({
18390
+ messages: args.ptyMessages,
18391
+ transcriptAuthority: "daemon",
18392
+ coverage: args.coverage || "current-turn",
18393
+ status: args.returnedStatus
18394
+ });
18395
+ const next2 = { ...ms, selectedDaemonSource: "current-runtime-pty", transcriptAuthority: "daemon", runtimeMappingSafe: true };
18396
+ args.messageSourceRef.set(next2);
18397
+ return;
18398
+ }
18399
+ const safeRuntimeAckMessages = selectRuntimeInputAckMessages(args.ptyMessages);
18400
+ if (safeRuntimeAckMessages.length > 0) {
18401
+ args.apply({
18402
+ messages: safeRuntimeAckMessages,
18403
+ transcriptAuthority: "daemon",
18404
+ coverage: "tail",
18405
+ status: coerceUnsafeNativeFallbackStatus(args.returnedStatus, args.activeModal)
18406
+ });
18407
+ const next2 = { ...ms, ptyStatusApprovalOnly: true };
18408
+ args.messageSourceRef.set(next2);
18409
+ return;
18410
+ }
18411
+ const exactRuntimeMirrorMessages = readExactRuntimeMirrorMessages({
18412
+ providerType: args.providerType,
18413
+ targetSessionId: typeof args.readChatArgs?.targetSessionId === "string" ? args.readChatArgs.targetSessionId : void 0,
18414
+ currentSessionId: typeof args.helpers.currentSession?.sessionId === "string" ? args.helpers.currentSession.sessionId : void 0,
18415
+ tailLimit: args.nativeHistoryLimit,
18416
+ historyBehavior: args.provider?.historyBehavior
18417
+ });
18418
+ if (exactRuntimeMirrorMessages.length > 0) {
18419
+ args.apply({
18420
+ messages: exactRuntimeMirrorMessages,
18421
+ transcriptAuthority: "daemon",
18422
+ coverage: "tail",
18423
+ status: coerceUnsafeNativeFallbackStatus(args.returnedStatus, args.activeModal)
18424
+ });
18425
+ const next2 = { ...ms, selectedDaemonSource: "exact-runtime-mirror", transcriptAuthority: "daemon", ptyStatusApprovalOnly: true };
18426
+ args.messageSourceRef.set(next2);
18427
+ return;
18428
+ }
18429
+ args.apply({
18430
+ messages: args.ptyMessages,
18431
+ coverage: args.coverage,
18432
+ status: coerceUnsafeNativeFallbackStatus(args.returnedStatus, args.activeModal)
18433
+ });
18434
+ const next = { ...ms, ptyStatusApprovalOnly: true };
18435
+ args.messageSourceRef.set(next);
17799
18436
  }
17800
18437
  function isUnsafeNativeTranscriptFallback(reason) {
17801
18438
  const value = String(reason || "").trim();
@@ -17867,8 +18504,14 @@ function isCurrentRuntimePtySafelyAttributed(args) {
17867
18504
  return true;
17868
18505
  }
17869
18506
  function supportsCliNativeTranscript(providerType, provider) {
17870
- if (CLI_NATIVE_TRANSCRIPT_PROVIDERS.has(providerType)) return true;
17871
- return provider?.category === "cli" && isNativeSourceCanonicalHistory(provider?.canonicalHistory);
18507
+ if (provider?.category === "cli" && isNativeSourceCanonicalHistory(provider?.canonicalHistory)) {
18508
+ return true;
18509
+ }
18510
+ if (CLI_NATIVE_TRANSCRIPT_PROVIDERS.has(providerType)) {
18511
+ warnLegacyNativeAllowlistHit(providerType);
18512
+ return true;
18513
+ }
18514
+ return false;
17872
18515
  }
17873
18516
  function getComparableVisibleText(message) {
17874
18517
  if (!message) return "";
@@ -17967,14 +18610,6 @@ function readLiveCodexWorkspaceNativeHistory(agentStr, args) {
17967
18610
  });
17968
18611
  return { ...history, lookup: "workspace" };
17969
18612
  }
17970
- function isNativeHistoryFreshEnough(args) {
17971
- const nativeNewest = getMessageNewestReceivedAt(args.nativeMessages);
17972
- const ptyNewest = getMessageNewestReceivedAt(args.ptyMessages);
17973
- if (nativeNewest > 0 && nativeNewest >= ptyNewest) return true;
17974
- const sourceMtimeMs = Number(args.sourceMtimeMs || 0);
17975
- if (sourceMtimeMs > 0 && Date.now() - sourceMtimeMs <= CLI_NATIVE_HISTORY_FRESH_MS) return true;
17976
- return ptyNewest === 0 && nativeNewest > 0;
17977
- }
17978
18613
  function shouldPreserveReadChatPayloadField(key) {
17979
18614
  return key === "messageSource" || key === "transcriptProvenance";
17980
18615
  }
@@ -18039,6 +18674,8 @@ function normalizeReadChatCommandStatus(status, activeModal) {
18039
18674
  case "disconnected":
18040
18675
  case "not_monitored":
18041
18676
  return "error";
18677
+ case "waiting_approval":
18678
+ return hasNonEmptyModalButtons(activeModal) ? "waiting_approval" : "generating";
18042
18679
  default:
18043
18680
  return raw;
18044
18681
  }
@@ -18087,6 +18724,36 @@ function finalizeStreamingMessagesWhenIdle(messages, status) {
18087
18724
  };
18088
18725
  });
18089
18726
  }
18727
+ function collapseAdjacentDuplicateChatMessages(messages) {
18728
+ if (!Array.isArray(messages) || messages.length <= 1) return messages;
18729
+ const result = [];
18730
+ let prevRoleKind = "";
18731
+ let prevStripped = "";
18732
+ for (const message of messages) {
18733
+ const role = typeof message.role === "string" ? message.role : "";
18734
+ const kind = typeof message.kind === "string" ? message.kind : "standard";
18735
+ const content = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.map((p) => typeof p?.text === "string" ? p.text : "").join("") : "";
18736
+ const strippedContent = content.replace(/\s+/g, "");
18737
+ if (!strippedContent || role === "system") {
18738
+ result.push(message);
18739
+ prevRoleKind = "";
18740
+ prevStripped = "";
18741
+ continue;
18742
+ }
18743
+ const roleKind = `${role}:${kind}`;
18744
+ const sameStripped = strippedContent === prevStripped && roleKind === prevRoleKind;
18745
+ if (result.length > 0 && sameStripped) {
18746
+ result[result.length - 1] = message;
18747
+ prevRoleKind = roleKind;
18748
+ prevStripped = strippedContent;
18749
+ continue;
18750
+ }
18751
+ result.push(message);
18752
+ prevRoleKind = roleKind;
18753
+ prevStripped = strippedContent;
18754
+ }
18755
+ return result;
18756
+ }
18090
18757
  function buildReadChatCommandResult(payload, args) {
18091
18758
  let validatedPayload;
18092
18759
  const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
@@ -18609,7 +19276,9 @@ async function handleReadChat(h, args) {
18609
19276
  const activeModal = parsedRecord.activeModal ?? parsedRecord.modal ?? null;
18610
19277
  const returnedStatus = normalizeCliReadChatStatus(parsedRecord.status, activeModal, adapter, adapterStatus, parsedRecord.messages);
18611
19278
  const runtimeMessageMerger = getTargetInstance(h, args);
18612
- const parsedMessages = finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus);
19279
+ const parsedMessages = collapseAdjacentDuplicateChatMessages(
19280
+ finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus)
19281
+ );
18613
19282
  const returnedMessages = runtimeMessageMerger?.category === "cli" && runtimeMessageMerger.type === adapter.cliType && typeof runtimeMessageMerger.mergeRuntimeChatMessages === "function" ? runtimeMessageMerger.mergeRuntimeChatMessages(parsedMessages) : parsedMessages;
18614
19283
  const providerType = provider?.type || adapter.cliType;
18615
19284
  let selectedMessages = returnedMessages;
@@ -18620,30 +19289,22 @@ async function handleReadChat(h, args) {
18620
19289
  let selectedStatus = returnedStatus;
18621
19290
  const sessionWorkspace = typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : typeof adapter.workingDir === "string" ? adapter.workingDir : void 0;
18622
19291
  const intendedWorkspace = typeof args?.workspace === "string" ? args.workspace : void 0;
18623
- let messageSource = buildCliMessageSourceProvenance({
18624
- selected: "pty-parser",
18625
- provider: adapter.cliType,
18626
- fallbackReason: supportsCliNativeTranscript(providerType, provider) ? "native_history_not_checked" : "provider_native_transcript_not_supported",
18627
- sessionWorkspace,
18628
- intendedWorkspace,
18629
- ptyMessages: returnedMessages,
18630
- returnedMessages,
18631
- ptyStatusApprovalOnly: false
18632
- });
18633
- if (supportsCliNativeTranscript(providerType, provider) && isNativeSourceCanonicalHistory(provider?.canonicalHistory)) {
18634
- const agentStr = provider?.type || args?.agentType || getCurrentProviderType(h, adapter.cliType);
18635
- const workspace = sessionWorkspace;
18636
- const nativeHistoryLimit = Math.max(
18637
- normalizeReadChatTailLimit(args) || 0,
18638
- returnedMessages.length,
18639
- 200
18640
- );
18641
- const nativeHistorySessionId = resolveCliNativeHistorySessionId(args, historySessionId, providerSessionId);
18642
- const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
18643
- const exactNativeHistoryScope = Boolean(
18644
- typeof args?.historySessionId === "string" && args.historySessionId.trim() || typeof args?.providerSessionId === "string" && args.providerSessionId.trim() || providerSessionId || nativeHistorySessionId && nativeHistorySessionId !== targetSessionId || h.currentSession?.sessionId === args?.targetSessionId && typeof h.currentSession?.providerSessionId === "string" && h.currentSession.providerSessionId.trim()
18645
- );
18646
- let nativeHistory = null;
19292
+ const supportsNative = supportsCliNativeTranscript(providerType, provider) && isNativeSourceCanonicalHistory(provider?.canonicalHistory);
19293
+ const agentStr = provider?.type || args?.agentType || getCurrentProviderType(h, adapter.cliType);
19294
+ const workspace = sessionWorkspace;
19295
+ const nativeHistoryLimit = Math.max(
19296
+ normalizeReadChatTailLimit(args) || 0,
19297
+ returnedMessages.length,
19298
+ 200
19299
+ );
19300
+ const nativeHistorySessionId = supportsNative ? resolveCliNativeHistorySessionId(args, historySessionId, providerSessionId) : void 0;
19301
+ const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
19302
+ const exactNativeHistoryScope = Boolean(
19303
+ typeof args?.historySessionId === "string" && args.historySessionId.trim() || typeof args?.providerSessionId === "string" && args.providerSessionId.trim() || providerSessionId || nativeHistorySessionId && nativeHistorySessionId !== targetSessionId || h.currentSession?.sessionId === args?.targetSessionId && typeof h.currentSession?.providerSessionId === "string" && h.currentSession.providerSessionId.trim()
19304
+ );
19305
+ let nativeHistory = null;
19306
+ let nativeHistoryError;
19307
+ if (supportsNative) {
18647
19308
  try {
18648
19309
  nativeHistory = readCliProviderNativeHistory(agentStr, {
18649
19310
  canonicalHistory: provider?.canonicalHistory,
@@ -18657,210 +19318,148 @@ async function handleReadChat(h, args) {
18657
19318
  excludeInProgressTurn: returnedStatus === "waiting_approval"
18658
19319
  });
18659
19320
  } catch (error) {
18660
- const fallbackReason = `native_history_error:${error?.message || String(error)}`;
18661
- messageSource = buildCliMessageSourceProvenance({
18662
- selected: "pty-parser",
18663
- provider: adapter.cliType,
18664
- fallbackReason,
18665
- sessionWorkspace,
18666
- intendedWorkspace,
18667
- ptyMessages: returnedMessages,
18668
- returnedMessages,
18669
- ptyStatusApprovalOnly: false
18670
- });
19321
+ nativeHistoryError = error;
18671
19322
  nativeHistory = null;
18672
19323
  }
18673
- if (nativeHistory) {
18674
- const nativeMessages = Array.isArray(nativeHistory.messages) ? normalizeNativeHistoryMessages(agentStr, nativeHistory.messages, nativeHistory?.providerSessionId) : [];
18675
- const historyProviderSessionId = typeof nativeHistory?.providerSessionId === "string" ? nativeHistory.providerSessionId : readHistorySessionIdFromMessages(nativeMessages) || nativeHistorySessionId || historySessionId;
18676
- const nativeHistoryCoverage = typeof nativeHistory?.nativeHistoryCoverage === "string" ? nativeHistory.nativeHistoryCoverage : void 0;
18677
- const partialReason = typeof nativeHistory?.partialReason === "string" ? nativeHistory.partialReason : void 0;
18678
- const unavailableReason = typeof nativeHistory?.unavailableReason === "string" ? nativeHistory.unavailableReason : void 0;
18679
- const lookup = nativeHistory.lookup === "workspace" ? "workspace" : "session";
18680
- const transcriptWorkspace = typeof nativeHistory?.workspace === "string" ? nativeHistory.workspace : nativeMessages.map((message) => typeof message?.workspace === "string" ? message.workspace.trim() : "").find(Boolean);
18681
- const nativeHistorySessionForMapping = adapter.cliType === "antigravity-cli" && historyProviderSessionId && nativeHistorySessionId && historyProviderSessionId !== nativeHistorySessionId ? void 0 : nativeHistorySessionId;
18682
- const safeMapping = hasSafeNativeHistoryMapping({
18683
- historySessionId: lookup === "workspace" ? void 0 : nativeHistorySessionForMapping,
18684
- providerSessionId: lookup === "workspace" ? void 0 : historyProviderSessionId || providerSessionId,
18685
- workspace,
18686
- nativeMessages,
19324
+ }
19325
+ const nativeMessages = nativeHistory && Array.isArray(nativeHistory.messages) ? normalizeNativeHistoryMessages(agentStr, nativeHistory.messages, nativeHistory.providerSessionId) : [];
19326
+ const historyProviderSessionId = typeof nativeHistory?.providerSessionId === "string" ? nativeHistory.providerSessionId : readHistorySessionIdFromMessages(nativeMessages) || nativeHistorySessionId || historySessionId;
19327
+ const lookup = nativeHistory?.lookup === "workspace" ? "workspace" : "session";
19328
+ const nativeHistorySessionForMapping = adapter.cliType === "antigravity-cli" && historyProviderSessionId && nativeHistorySessionId && historyProviderSessionId !== nativeHistorySessionId ? void 0 : nativeHistorySessionId;
19329
+ const safeMapping = supportsNative && nativeHistory ? hasSafeNativeHistoryMapping({
19330
+ historySessionId: lookup === "workspace" ? void 0 : nativeHistorySessionForMapping,
19331
+ providerSessionId: lookup === "workspace" ? void 0 : historyProviderSessionId || providerSessionId,
19332
+ workspace,
19333
+ nativeMessages,
19334
+ ptyMessages: returnedMessages,
19335
+ requireWorkspaceContentOverlap: lookup === "workspace" && !exactNativeHistoryScope
19336
+ }) : false;
19337
+ const machineSessionKey = String(
19338
+ args?.targetSessionId || providerSessionId || historySessionId || h.currentSession?.sessionId || ""
19339
+ );
19340
+ const primary = decideCliReadChatSource({
19341
+ providerType,
19342
+ provider,
19343
+ sessionId: machineSessionKey,
19344
+ nativeHistoryResult: nativeHistory,
19345
+ nativeHistoryError,
19346
+ safeMapping,
19347
+ sessionWorkspace,
19348
+ intendedWorkspace,
19349
+ ptyMessages: returnedMessages,
19350
+ // Start with PTY visible; decideCliReadChatSource flips this
19351
+ // to true when the machine actually selects native-history.
19352
+ ptyStatusApprovalOnly: false
19353
+ });
19354
+ let messageSource = primary.messageSource;
19355
+ if (primary.nativeSelected) {
19356
+ selectedMessages = finalizeStreamingMessagesWhenIdle(primary.nativeMessages, returnedStatus);
19357
+ selectedProviderSessionId = historyProviderSessionId || providerSessionId;
19358
+ selectedTranscriptAuthority = "provider";
19359
+ selectedCoverage = nativeHistory?.hasMore ? "tail" : "full";
19360
+ } else if (supportsNative) {
19361
+ const liveCurrentRuntimePtySafe = isCurrentRuntimePtySafelyAttributed({
19362
+ adapter,
19363
+ helpers: h,
19364
+ readChatArgs: args,
19365
+ sessionWorkspace,
19366
+ intendedWorkspace,
19367
+ ptyMessages: returnedMessages
19368
+ });
19369
+ const mayProbeLiveCodexWorkspaceNative = adapter.cliType === "codex-cli" && liveCurrentRuntimePtySafe && !(typeof args?.providerSessionId === "string" && args.providerSessionId.trim()) && !(providerSessionId && providerSessionId.trim()) && (!historyProviderSessionId || historyProviderSessionId === nativeHistorySessionId || historyProviderSessionId === historySessionId);
19370
+ const liveWorkspaceNativeHistory = mayProbeLiveCodexWorkspaceNative ? readLiveCodexWorkspaceNativeHistory(agentStr, {
19371
+ canonicalHistory: provider?.canonicalHistory,
19372
+ workspace,
19373
+ offset: 0,
19374
+ limit: nativeHistoryLimit,
19375
+ excludeRecentCount: 0,
19376
+ historyBehavior: provider?.historyBehavior,
19377
+ scripts: provider?.scripts
19378
+ }) : null;
19379
+ const liveWorkspaceNativeMessages = Array.isArray(liveWorkspaceNativeHistory?.messages) ? normalizeNativeHistoryMessages(agentStr, liveWorkspaceNativeHistory.messages, liveWorkspaceNativeHistory?.providerSessionId) : [];
19380
+ const liveWorkspaceNativeProviderSessionId = typeof liveWorkspaceNativeHistory?.providerSessionId === "string" ? liveWorkspaceNativeHistory.providerSessionId : readHistorySessionIdFromMessages(liveWorkspaceNativeMessages);
19381
+ const liveWorkspaceNativeSafeMapping = liveWorkspaceNativeMessages.length > 0 && hasSafeNativeHistoryMapping({
19382
+ workspace,
19383
+ nativeMessages: liveWorkspaceNativeMessages,
19384
+ ptyMessages: returnedMessages,
19385
+ requireWorkspaceContentOverlap: true
19386
+ });
19387
+ if (liveWorkspaceNativeHistory) {
19388
+ const liveDecision = decideCliReadChatSource({
19389
+ providerType,
19390
+ provider,
19391
+ // Distinct session key so a transient codex live-probe does not
19392
+ // clobber the primary session's lock. The machine treats this
19393
+ // as its own session; the primary session's state is untouched.
19394
+ sessionId: `${machineSessionKey}::live-workspace`,
19395
+ nativeHistoryResult: liveWorkspaceNativeHistory,
19396
+ safeMapping: liveWorkspaceNativeSafeMapping,
19397
+ sessionWorkspace,
19398
+ intendedWorkspace,
18687
19399
  ptyMessages: returnedMessages,
18688
- requireWorkspaceContentOverlap: lookup === "workspace" && !exactNativeHistoryScope
18689
- });
18690
- const freshEnough = isNativeHistoryFreshEnough({
18691
- sourceMtimeMs: nativeHistory.sourceMtimeMs,
18692
- nativeMessages,
18693
- ptyMessages: returnedMessages
19400
+ ptyStatusApprovalOnly: true
18694
19401
  });
18695
- const nativeUsableForChatMessages = nativeHistory.source === "provider-native" && nativeMessages.length > 0 && nativeHistoryCoverage !== "partial" && nativeHistoryCoverage !== "unavailable" && safeMapping;
18696
- const NATIVE_ANCHOR_TTL_MS = 30 * 6e4;
18697
- const nativeAnchoredAt = adapter.nativeHistoryAnchoredAt ?? 0;
18698
- const nativeIsAnchored = nativeAnchoredAt > 0 && Date.now() - nativeAnchoredAt < NATIVE_ANCHOR_TTL_MS;
18699
- const allowStaleNativeChatMessages = (adapter.cliType === "antigravity-cli" || nativeIsAnchored) && nativeUsableForChatMessages;
18700
- if (nativeUsableForChatMessages && (freshEnough || allowStaleNativeChatMessages)) {
18701
- adapter.nativeHistoryAnchoredAt = Date.now();
18702
- selectedMessages = finalizeStreamingMessagesWhenIdle(nativeMessages, returnedStatus);
18703
- selectedProviderSessionId = historyProviderSessionId || providerSessionId;
19402
+ if (liveDecision.nativeSelected) {
19403
+ selectedMessages = finalizeStreamingMessagesWhenIdle(liveDecision.nativeMessages, returnedStatus);
19404
+ selectedProviderSessionId = liveWorkspaceNativeProviderSessionId || providerSessionId;
18704
19405
  selectedTranscriptAuthority = "provider";
18705
- selectedCoverage = nativeHistory.hasMore ? "tail" : "full";
18706
- messageSource = buildCliMessageSourceProvenance({
18707
- selected: "native-history",
18708
- provider: adapter.cliType,
18709
- nativeHandle: selectedProviderSessionId || nativeHistorySessionId || historySessionId,
18710
- sessionWorkspace,
18711
- intendedWorkspace,
18712
- transcriptWorkspace,
18713
- nativeSource: nativeHistory.source,
18714
- sourcePath: nativeHistory.sourcePath,
18715
- sourceMtimeMs: nativeHistory.sourceMtimeMs,
18716
- nativeHistoryCoverage,
18717
- partialReason,
18718
- unavailableReason,
18719
- nativeMessages,
18720
- ptyMessages: returnedMessages,
18721
- returnedMessages: selectedMessages,
18722
- safeMapping,
18723
- freshEnough,
18724
- ptyStatusApprovalOnly: true
18725
- });
19406
+ selectedCoverage = liveWorkspaceNativeHistory.hasMore ? "tail" : "full";
19407
+ messageSource = liveDecision.messageSource;
19408
+ messageSource.selectedDaemonSource = "live-workspace-native-history";
19409
+ messageSource.runtimeMappingSafe = true;
18726
19410
  } else {
18727
- if (!nativeUsableForChatMessages && adapter.nativeHistoryAnchoredAt) {
18728
- adapter.nativeHistoryAnchoredAt = 0;
18729
- }
18730
- const liveCurrentRuntimePtySafe = isCurrentRuntimePtySafelyAttributed({
19411
+ applyUnsafeNativeDaemonFallback({
19412
+ providerType,
18731
19413
  adapter,
18732
19414
  helpers: h,
18733
19415
  readChatArgs: args,
18734
19416
  sessionWorkspace,
18735
19417
  intendedWorkspace,
18736
- ptyMessages: returnedMessages
18737
- });
18738
- const mayProbeLiveCodexWorkspaceNative = adapter.cliType === "codex-cli" && liveCurrentRuntimePtySafe && !(typeof args?.providerSessionId === "string" && args.providerSessionId.trim()) && !(providerSessionId && providerSessionId.trim()) && (!historyProviderSessionId || historyProviderSessionId === nativeHistorySessionId || historyProviderSessionId === historySessionId);
18739
- const liveWorkspaceNativeHistory = mayProbeLiveCodexWorkspaceNative ? readLiveCodexWorkspaceNativeHistory(agentStr, {
18740
- canonicalHistory: provider?.canonicalHistory,
18741
- workspace,
18742
- offset: 0,
18743
- limit: nativeHistoryLimit,
18744
- excludeRecentCount: 0,
18745
- historyBehavior: provider?.historyBehavior,
18746
- scripts: provider?.scripts
18747
- }) : null;
18748
- const liveWorkspaceNativeMessages = Array.isArray(liveWorkspaceNativeHistory?.messages) ? normalizeNativeHistoryMessages(agentStr, liveWorkspaceNativeHistory.messages, liveWorkspaceNativeHistory?.providerSessionId) : [];
18749
- const liveWorkspaceNativeProviderSessionId = typeof liveWorkspaceNativeHistory?.providerSessionId === "string" ? liveWorkspaceNativeHistory.providerSessionId : readHistorySessionIdFromMessages(liveWorkspaceNativeMessages);
18750
- const liveWorkspaceTranscriptWorkspace = typeof liveWorkspaceNativeHistory?.workspace === "string" ? liveWorkspaceNativeHistory.workspace : liveWorkspaceNativeMessages.map((message) => typeof message?.workspace === "string" ? message.workspace.trim() : "").find(Boolean);
18751
- const liveWorkspaceNativeSafeMapping = liveWorkspaceNativeMessages.length > 0 && hasSafeNativeHistoryMapping({
18752
- workspace,
18753
- nativeMessages: liveWorkspaceNativeMessages,
18754
19418
  ptyMessages: returnedMessages,
18755
- requireWorkspaceContentOverlap: true
18756
- });
18757
- const liveWorkspaceNativeFreshEnough = liveWorkspaceNativeMessages.length > 0 && isNativeHistoryFreshEnough({
18758
- sourceMtimeMs: liveWorkspaceNativeHistory?.sourceMtimeMs,
18759
- nativeMessages: liveWorkspaceNativeMessages,
18760
- ptyMessages: returnedMessages
19419
+ nativeHistoryLimit,
19420
+ provider,
19421
+ messageSourceRef: { set(value) {
19422
+ messageSource = value;
19423
+ }, get() {
19424
+ return messageSource;
19425
+ } },
19426
+ apply(selection) {
19427
+ selectedMessages = selection.messages;
19428
+ selectedTranscriptAuthority = selection.transcriptAuthority;
19429
+ selectedCoverage = selection.coverage ?? coverage;
19430
+ selectedStatus = selection.status ?? returnedStatus;
19431
+ },
19432
+ activeModal,
19433
+ returnedStatus,
19434
+ coverage
18761
19435
  });
18762
- const liveWorkspaceNativeUsable = liveWorkspaceNativeHistory?.source === "provider-native" && liveWorkspaceNativeMessages.length > 0 && liveWorkspaceNativeHistory?.nativeHistoryCoverage !== "partial" && liveWorkspaceNativeHistory?.nativeHistoryCoverage !== "unavailable" && liveWorkspaceNativeSafeMapping && liveWorkspaceNativeFreshEnough;
18763
- if (liveWorkspaceNativeUsable) {
18764
- selectedMessages = finalizeStreamingMessagesWhenIdle(liveWorkspaceNativeMessages, returnedStatus);
18765
- selectedProviderSessionId = liveWorkspaceNativeProviderSessionId || providerSessionId;
18766
- selectedTranscriptAuthority = "provider";
18767
- selectedCoverage = liveWorkspaceNativeHistory.hasMore ? "tail" : "full";
18768
- messageSource = buildCliMessageSourceProvenance({
18769
- selected: "native-history",
18770
- provider: adapter.cliType,
18771
- nativeHandle: selectedProviderSessionId || nativeHistorySessionId || historySessionId,
18772
- sessionWorkspace,
18773
- intendedWorkspace,
18774
- transcriptWorkspace: liveWorkspaceTranscriptWorkspace,
18775
- nativeSource: liveWorkspaceNativeHistory.source,
18776
- sourcePath: liveWorkspaceNativeHistory.sourcePath,
18777
- sourceMtimeMs: liveWorkspaceNativeHistory.sourceMtimeMs,
18778
- nativeHistoryCoverage: liveWorkspaceNativeHistory.nativeHistoryCoverage,
18779
- partialReason: liveWorkspaceNativeHistory.partialReason,
18780
- unavailableReason: liveWorkspaceNativeHistory.unavailableReason,
18781
- nativeMessages: liveWorkspaceNativeMessages,
18782
- ptyMessages: returnedMessages,
18783
- returnedMessages: selectedMessages,
18784
- safeMapping: true,
18785
- freshEnough: true,
18786
- ptyStatusApprovalOnly: true
18787
- });
18788
- messageSource.selectedDaemonSource = "live-workspace-native-history";
18789
- messageSource.runtimeMappingSafe = true;
18790
- } else {
18791
- const fallbackReason = buildNativeHistoryFallbackReason({
18792
- providerType,
18793
- provider,
18794
- nativeSource: nativeHistory.source,
18795
- nativeHistoryCoverage,
18796
- unavailableReason,
18797
- nativeMessageCount: nativeMessages.length,
18798
- safeMapping,
18799
- freshEnough
18800
- });
18801
- const unsafeNativeFallback = adapter.cliType === "codex-cli" && isUnsafeNativeTranscriptFallback(fallbackReason);
18802
- const safeCurrentRuntimePtyMessages = unsafeNativeFallback && isCurrentRuntimePtySafelyAttributed({
18803
- adapter,
18804
- helpers: h,
18805
- readChatArgs: args,
18806
- sessionWorkspace,
18807
- intendedWorkspace,
18808
- ptyMessages: returnedMessages
18809
- });
18810
- const safeRuntimeAckMessages = unsafeNativeFallback && !safeCurrentRuntimePtyMessages ? selectRuntimeInputAckMessages(returnedMessages) : [];
18811
- const exactRuntimeMirrorMessages = unsafeNativeFallback && !safeCurrentRuntimePtyMessages && safeRuntimeAckMessages.length === 0 ? readExactRuntimeMirrorMessages({
18812
- providerType,
18813
- targetSessionId: typeof args?.targetSessionId === "string" ? args.targetSessionId : void 0,
18814
- currentSessionId: typeof h.currentSession?.sessionId === "string" ? h.currentSession.sessionId : void 0,
18815
- tailLimit: nativeHistoryLimit,
18816
- historyBehavior: provider?.historyBehavior
18817
- }) : [];
18818
- const safeDaemonMessages = safeRuntimeAckMessages.length > 0 ? safeRuntimeAckMessages : exactRuntimeMirrorMessages;
18819
- if (unsafeNativeFallback) {
18820
- if (safeCurrentRuntimePtyMessages) {
18821
- selectedMessages = returnedMessages;
18822
- selectedTranscriptAuthority = "daemon";
18823
- selectedCoverage = coverage || "current-turn";
18824
- selectedStatus = returnedStatus;
18825
- } else {
18826
- selectedMessages = safeDaemonMessages;
18827
- selectedTranscriptAuthority = safeDaemonMessages.length > 0 ? "daemon" : void 0;
18828
- selectedCoverage = safeDaemonMessages.length > 0 ? "tail" : void 0;
18829
- selectedStatus = coerceUnsafeNativeFallbackStatus(returnedStatus, activeModal);
18830
- }
18831
- }
18832
- messageSource = buildCliMessageSourceProvenance({
18833
- selected: "pty-parser",
18834
- provider: adapter.cliType,
18835
- nativeHandle: historyProviderSessionId || nativeHistorySessionId || historySessionId,
18836
- sessionWorkspace,
18837
- intendedWorkspace,
18838
- transcriptWorkspace,
18839
- fallbackReason,
18840
- nativeSource: nativeHistory.source,
18841
- sourcePath: nativeHistory.sourcePath,
18842
- sourceMtimeMs: nativeHistory.sourceMtimeMs,
18843
- nativeHistoryCoverage,
18844
- partialReason,
18845
- unavailableReason,
18846
- nativeMessages,
18847
- ptyMessages: returnedMessages,
18848
- returnedMessages: unsafeNativeFallback && !safeCurrentRuntimePtyMessages ? safeDaemonMessages : returnedMessages,
18849
- safeMapping,
18850
- freshEnough,
18851
- ptyStatusApprovalOnly: unsafeNativeFallback && !safeCurrentRuntimePtyMessages
18852
- });
18853
- if (safeCurrentRuntimePtyMessages) {
18854
- messageSource.selectedDaemonSource = "current-runtime-pty";
18855
- messageSource.transcriptAuthority = "daemon";
18856
- messageSource.runtimeMappingSafe = true;
18857
- }
18858
- if (unsafeNativeFallback && exactRuntimeMirrorMessages.length > 0) {
18859
- messageSource.selectedDaemonSource = "exact-runtime-mirror";
18860
- messageSource.transcriptAuthority = "daemon";
18861
- }
18862
- }
18863
19436
  }
19437
+ } else {
19438
+ applyUnsafeNativeDaemonFallback({
19439
+ providerType,
19440
+ adapter,
19441
+ helpers: h,
19442
+ readChatArgs: args,
19443
+ sessionWorkspace,
19444
+ intendedWorkspace,
19445
+ ptyMessages: returnedMessages,
19446
+ nativeHistoryLimit,
19447
+ provider,
19448
+ messageSourceRef: { set(value) {
19449
+ messageSource = value;
19450
+ }, get() {
19451
+ return messageSource;
19452
+ } },
19453
+ apply(selection) {
19454
+ selectedMessages = selection.messages;
19455
+ selectedTranscriptAuthority = selection.transcriptAuthority;
19456
+ selectedCoverage = selection.coverage ?? coverage;
19457
+ selectedStatus = selection.status ?? returnedStatus;
19458
+ },
19459
+ activeModal,
19460
+ returnedStatus,
19461
+ coverage
19462
+ });
18864
19463
  }
18865
19464
  }
18866
19465
  LOG.debug("Command", `[read_chat] cli-like parsed provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord.status || "")} parsedMsgCount=${parsedRecord.messages.length} returnedMsgCount=${returnedMessages.length}`);
@@ -18893,10 +19492,8 @@ async function handleReadChat(h, args) {
18893
19492
  const agentStr = provider?.type || args?.agentType || getCurrentProviderType(h);
18894
19493
  const workspace = typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
18895
19494
  const intendedWorkspace = typeof args?.workspace === "string" ? args.workspace : void 0;
18896
- const exactNativeHistoryScope = Boolean(
18897
- typeof args?.targetSessionId === "string" && args.targetSessionId.trim() || typeof args?.historySessionId === "string" && args.historySessionId.trim() || typeof args?.providerSessionId === "string" && args.providerSessionId.trim() || h.currentSession?.sessionId === args?.targetSessionId && typeof h.currentSession?.providerSessionId === "string" && h.currentSession.providerSessionId.trim()
18898
- );
18899
- const history = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.canonicalHistory) ? readCliProviderNativeHistory(agentStr, {
19495
+ const supportsNative = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.canonicalHistory);
19496
+ const history = supportsNative ? readCliProviderNativeHistory(agentStr, {
18900
19497
  canonicalHistory: provider?.canonicalHistory,
18901
19498
  historySessionId,
18902
19499
  workspace,
@@ -18915,65 +19512,44 @@ async function handleReadChat(h, args) {
18915
19512
  historyBehavior: provider?.historyBehavior,
18916
19513
  scripts: provider?.scripts
18917
19514
  });
18918
- const lookup = history.lookup === "workspace" ? "workspace" : "session";
19515
+ const lookup = history?.lookup === "workspace" ? "workspace" : "session";
18919
19516
  const historyMessages = Array.isArray(history?.messages) ? normalizeNativeHistoryMessages(agentStr, history.messages, history?.providerSessionId) : [];
18920
19517
  const historyProviderSessionId = typeof history?.providerSessionId === "string" ? history.providerSessionId : readHistorySessionIdFromMessages(historyMessages) || historySessionId;
18921
- const nativeHistoryCoverage = typeof history?.nativeHistoryCoverage === "string" ? history.nativeHistoryCoverage : void 0;
18922
- const partialReason = typeof history?.partialReason === "string" ? history.partialReason : void 0;
18923
- const unavailableReason = typeof history?.unavailableReason === "string" ? history.unavailableReason : void 0;
18924
- const transcriptWorkspace = typeof history?.workspace === "string" ? history.workspace : historyMessages.map((message) => typeof message?.workspace === "string" ? message.workspace.trim() : "").find(Boolean);
18925
- const safeMapping = supportsCliNativeTranscript(agentStr, provider) ? hasSafeNativeHistoryMapping({
19518
+ const safeMapping = supportsNative ? hasSafeNativeHistoryMapping({
18926
19519
  historySessionId: lookup === "workspace" ? void 0 : historySessionId,
18927
19520
  providerSessionId: lookup === "workspace" ? void 0 : historyProviderSessionId,
18928
19521
  workspace,
18929
19522
  nativeMessages: historyMessages
18930
19523
  }) : false;
18931
- const nativeSelected = supportsCliNativeTranscript(agentStr, provider) && history.source === "provider-native" && historyMessages.length > 0 && nativeHistoryCoverage !== "partial" && nativeHistoryCoverage !== "unavailable" && safeMapping;
18932
- const messageSource = buildCliMessageSourceProvenance({
18933
- selected: nativeSelected ? "native-history" : "pty-parser",
18934
- provider: agentStr,
18935
- nativeHandle: historyProviderSessionId || historySessionId,
19524
+ const machineSessionKey = String(
19525
+ args?.targetSessionId || historyProviderSessionId || historySessionId || h.currentSession?.sessionId || ""
19526
+ );
19527
+ const decision = decideCliReadChatSource({
19528
+ providerType: agentStr,
19529
+ provider,
19530
+ sessionId: machineSessionKey,
19531
+ nativeHistoryResult: history,
19532
+ safeMapping,
18936
19533
  sessionWorkspace: workspace,
18937
19534
  intendedWorkspace,
18938
- transcriptWorkspace,
18939
- fallbackReason: nativeSelected ? void 0 : buildNativeHistoryFallbackReason({
18940
- providerType: agentStr,
18941
- provider,
18942
- nativeSource: history.source,
18943
- nativeHistoryCoverage,
18944
- unavailableReason,
18945
- nativeMessageCount: historyMessages.length,
18946
- safeMapping,
18947
- freshEnough: true
18948
- }),
18949
- nativeSource: history.source,
18950
- sourcePath: history.sourcePath,
18951
- sourceMtimeMs: history.sourceMtimeMs,
18952
- nativeHistoryCoverage,
18953
- partialReason,
18954
- unavailableReason,
18955
- nativeMessages: historyMessages,
18956
- returnedMessages: historyMessages,
18957
- safeMapping,
18958
- freshEnough: true,
19535
+ ptyMessages: [],
18959
19536
  ptyStatusApprovalOnly: false
18960
19537
  });
18961
- const requiresNativeSource = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.canonicalHistory);
18962
- if (requiresNativeSource && !nativeSelected) {
19538
+ if (supportsNative && !decision.nativeSelected) {
18963
19539
  return {
18964
19540
  success: false,
18965
19541
  code: "native_history_not_safely_available",
18966
19542
  error: "Provider-native history was not safely available for the requested CLI session.",
18967
19543
  providerSessionId: historyProviderSessionId,
18968
- messageSource,
18969
- transcriptProvenance: messageSource
19544
+ messageSource: decision.messageSource,
19545
+ transcriptProvenance: decision.messageSource
18970
19546
  };
18971
19547
  }
18972
19548
  return buildReadChatCommandResult({
18973
19549
  messages: historyMessages,
18974
19550
  status: "idle",
18975
- messageSource,
18976
- transcriptProvenance: messageSource,
19551
+ messageSource: decision.messageSource,
19552
+ transcriptProvenance: decision.messageSource,
18977
19553
  ...typeof history?.title === "string" ? { title: history.title } : {},
18978
19554
  ...historyProviderSessionId ? { providerSessionId: historyProviderSessionId } : {},
18979
19555
  ...provider?.historyBehavior?.transcriptAuthority === "provider" || provider?.historyBehavior?.transcriptAuthority === "daemon" ? { transcriptAuthority: (provider?.historyBehavior).transcriptAuthority } : {},
@@ -25196,6 +25772,10 @@ function validateCanonicalHistory(raw, errors) {
25196
25772
  if (mode !== void 0 && !["native-source", "materialized-mirror", "disabled"].includes(String(mode))) {
25197
25773
  errors.push("canonicalHistory.mode must be one of: native-source, materialized-mirror, disabled");
25198
25774
  }
25775
+ const chatContractVersion = canonicalHistory.contractVersion;
25776
+ if (chatContractVersion !== void 0 && chatContractVersion !== "1.0" && chatContractVersion !== "2.0") {
25777
+ errors.push(`canonicalHistory.contractVersion must be '1.0' or '2.0' when provided (got ${JSON.stringify(chatContractVersion)})`);
25778
+ }
25199
25779
  const scripts = canonicalHistory.scripts;
25200
25780
  if (scripts === void 0) return;
25201
25781
  if (!scripts || typeof scripts !== "object" || Array.isArray(scripts)) {
@@ -26434,7 +27014,7 @@ var ProviderLoader = class _ProviderLoader {
26434
27014
  return args ? args.map((arg) => /\s/.test(arg) ? JSON.stringify(arg) : arg).join(" ") : "";
26435
27015
  }
26436
27016
  const schemaDef = this.getSettingsSchema(providerType)[key];
26437
- const defaultVal = schemaDef ? key === "autoApprove" && schemaDef.type === "boolean" ? true : schemaDef.default : void 0;
27017
+ const defaultVal = schemaDef ? schemaDef.default : void 0;
26438
27018
  const config = this.readConfig();
26439
27019
  const userVal = config?.providerSettings?.[providerType]?.[key];
26440
27020
  return userVal !== void 0 ? userVal : defaultVal;
@@ -26536,7 +27116,6 @@ var ProviderLoader = class _ProviderLoader {
26536
27116
  if (result.autoApprove?.type === "boolean") {
26537
27117
  result.autoApprove = {
26538
27118
  ...result.autoApprove,
26539
- default: true,
26540
27119
  public: true,
26541
27120
  label: result.autoApprove.label || "Auto Approve",
26542
27121
  description: result.autoApprove.description || "Automatically approve actionable prompts without sending approval alerts."
@@ -26558,7 +27137,10 @@ var ProviderLoader = class _ProviderLoader {
26558
27137
  if (!provider.settings?.autoApprove) {
26559
27138
  result.autoApprove = {
26560
27139
  type: "boolean",
26561
- default: true,
27140
+ // (fix) Safe default is *off*. Auto-approving every modal without the
27141
+ // user opting in produced silent-bash-execution surprises and the
27142
+ // "Auto-approved: ..." system-message flood seen on AGY/Codex.
27143
+ default: false,
26562
27144
  public: true,
26563
27145
  label: "Auto Approve",
26564
27146
  description: "Automatically approve actionable prompts without sending approval alerts."
@@ -27855,15 +28437,22 @@ function getSessionMessageUpdatedAt(session) {
27855
28437
  return getMessageEventTime(lastMessage);
27856
28438
  }
27857
28439
  function getSessionCompletionMarker(session) {
27858
- const lastMessage = session.activeChat?.messages?.at?.(-1);
27859
- if (!lastMessage) return "";
27860
- const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
27861
- if (role === "user" || role === "human" || role === "system") return "";
27862
- if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
27863
- if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
27864
- if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
27865
- const timestamp = getMessageEventTime(lastMessage);
27866
- return timestamp > 0 ? `ts:${timestamp}` : "";
28440
+ const messages = session.activeChat?.messages;
28441
+ if (!Array.isArray(messages) || messages.length === 0) return "";
28442
+ for (let i = messages.length - 1; i >= 0; i -= 1) {
28443
+ const m = messages[i];
28444
+ const role = typeof m?.role === "string" ? m.role : "";
28445
+ const kind = typeof m?.kind === "string" ? m.kind : "";
28446
+ if (role === "user" || role === "human") return "";
28447
+ if (role === "system") continue;
28448
+ if (kind === "tool") continue;
28449
+ if (typeof m._turnKey === "string" && m._turnKey) return `turn:${m._turnKey}`;
28450
+ if (typeof m.id === "string" && m.id) return `id:${m.id}`;
28451
+ if (typeof m.index === "number" && Number.isFinite(m.index)) return `idx:${m.index}`;
28452
+ const timestamp = getMessageEventTime(m);
28453
+ return timestamp > 0 ? `ts:${timestamp}` : "";
28454
+ }
28455
+ return "";
27867
28456
  }
27868
28457
  function getSessionLastUsedAt(session) {
27869
28458
  return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
@@ -27878,7 +28467,8 @@ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRo
27878
28467
  if (status === "generating" || status === "starting") {
27879
28468
  return { unread: false, inboxBucket: "working" };
27880
28469
  }
27881
- const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human" && lastRole !== "system";
28470
+ const ignorableTrailingRoles = lastRole === "user" || lastRole === "human" || lastRole === "system" || lastRole === "tool";
28471
+ const unread = completionMarker ? seenCompletionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && !ignorableTrailingRoles : hasContentChange && lastUsedAt > lastSeenAt && !ignorableTrailingRoles;
27882
28472
  return { unread, inboxBucket: unread ? "task_complete" : "idle" };
27883
28473
  }
27884
28474
  function projectLiveSessionFromFull(session) {
@@ -31242,7 +31832,8 @@ var DaemonCommandRouter = class {
31242
31832
  }
31243
31833
  case "get_pending_mesh_events": {
31244
31834
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
31245
- const events = drainPendingMeshCoordinatorEvents(meshId || void 0);
31835
+ const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
31836
+ const events = drainPendingMeshCoordinatorEvents(meshId || void 0, coordinatorDaemonId);
31246
31837
  return { success: true, events };
31247
31838
  }
31248
31839
  case "launch_cli":
@@ -33218,7 +33809,8 @@ ${block2}`);
33218
33809
  finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
33219
33810
  nodeStatuses.push(status);
33220
33811
  }
33221
- const pendingCoordinatorEvents = drainPendingMeshCoordinatorEvents(meshId);
33812
+ const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
33813
+ const pendingCoordinatorEvents = drainPendingMeshCoordinatorEvents(meshId, callerCoordinatorDaemonId);
33222
33814
  const previewFreshness = (() => {
33223
33815
  const localRepoRoot = nodeStatuses.map((node) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace)).find((candidate) => !!candidate && fs11.existsSync(candidate));
33224
33816
  return localRepoRoot ? buildPreviewFreshness(localRepoRoot) : void 0;
@@ -33696,6 +34288,7 @@ function prepareSessionChatTailUpdate(input) {
33696
34288
  const title = typeof result.title === "string" ? result.title : void 0;
33697
34289
  const activeModal = normalizeChatTailActiveModal(result.activeModal);
33698
34290
  const status = typeof result.status === "string" ? result.status : "idle";
34291
+ const messageSource = result.messageSource && typeof result.messageSource === "object" ? result.messageSource : void 0;
33699
34292
  const deliverySignature = buildChatTailDeliverySignature({
33700
34293
  sessionId: input.sessionId,
33701
34294
  ...input.historySessionId ? { historySessionId: input.historySessionId } : {},
@@ -33728,7 +34321,8 @@ function prepareSessionChatTailUpdate(input) {
33728
34321
  messages,
33729
34322
  status,
33730
34323
  ...title ? { title } : {},
33731
- ...activeModal ? { activeModal } : {}
34324
+ ...activeModal ? { activeModal } : {},
34325
+ ...messageSource ? { messageSource } : {}
33732
34326
  }
33733
34327
  };
33734
34328
  }