@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.mjs CHANGED
@@ -4343,7 +4343,14 @@ var init_ghostty_vt_backend = __esm({
4343
4343
  this.terminal.write(data);
4344
4344
  }
4345
4345
  getText() {
4346
- return this.terminal.formatPlainText({ trim: true }) || "";
4346
+ const raw = this.terminal.formatPlainText({ trim: false }) || "";
4347
+ if (!raw) return "";
4348
+ const lines = raw.split("\n").map((row) => row.replace(/\s+$/, ""));
4349
+ let first = 0;
4350
+ let last = lines.length;
4351
+ while (first < last && !lines[first]) first += 1;
4352
+ while (last > first && !lines[last - 1]) last -= 1;
4353
+ return lines.slice(first, last).join("\n");
4347
4354
  }
4348
4355
  getCursorPosition() {
4349
4356
  return this.terminal.getCursorPosition();
@@ -4397,7 +4404,8 @@ var init_xterm_backend = __esm({
4397
4404
  const lines = [];
4398
4405
  for (let i = start; i < end; i++) {
4399
4406
  const line = buffer.getLine(i);
4400
- lines.push(line ? line.translateToString(true) : "");
4407
+ const raw = line ? line.translateToString(false) : "";
4408
+ lines.push(raw.replace(/\s+$/, ""));
4401
4409
  }
4402
4410
  let first = 0;
4403
4411
  let last = lines.length;
@@ -4932,8 +4940,13 @@ var init_provider_cli_shared = __esm({
4932
4940
  this.ensureRow();
4933
4941
  if (final === "A") this.row = Math.max(0, this.row - count);
4934
4942
  else if (final === "B") this.row += count;
4935
- else if (final === "C") this.col += count;
4936
- else if (final === "D") this.col = Math.max(0, this.col - count);
4943
+ else if (final === "C") {
4944
+ const line = this.lines[this.row];
4945
+ for (let c = this.col; c < this.col + count; c += 1) {
4946
+ if (line[c] === void 0) line[c] = " ";
4947
+ }
4948
+ this.col += count;
4949
+ } else if (final === "D") this.col = Math.max(0, this.col - count);
4937
4950
  else if (final === "G") this.col = Math.max(0, count - 1);
4938
4951
  else if (final === "H" || final === "f") {
4939
4952
  const parts = String(params || "").split(";");
@@ -5106,7 +5119,8 @@ function buildCliParseInput(options) {
5106
5119
  partialResponse,
5107
5120
  isWaitingForResponse,
5108
5121
  scope,
5109
- runtimeSettings
5122
+ runtimeSettings,
5123
+ spawnAt
5110
5124
  } = options;
5111
5125
  const buffer = scope ? sliceFromOffset(accumulatedBuffer, scope.bufferStart) : accumulatedBuffer;
5112
5126
  const rawBuffer = scope ? sliceFromOffset(accumulatedRawBuffer, scope.rawBufferStart) : accumulatedRawBuffer;
@@ -5128,7 +5142,8 @@ function buildCliParseInput(options) {
5128
5142
  partialResponse,
5129
5143
  isWaitingForResponse,
5130
5144
  promptText: scope?.prompt || "",
5131
- settings: { ...runtimeSettings }
5145
+ settings: { ...runtimeSettings },
5146
+ ...typeof spawnAt === "number" && spawnAt > 0 ? { spawnAt } : {}
5132
5147
  };
5133
5148
  }
5134
5149
  function summarizeCliTraceText(text, max = 800) {
@@ -5144,7 +5159,7 @@ var init_provider_cli_parse = __esm({
5144
5159
  });
5145
5160
 
5146
5161
  // src/cli-adapters/cli-state-engine.ts
5147
- var SCRIPT_STATUS_DEBOUNCE_MS, MAX_FINISH_RETRIES, FINISH_RETRY_DELAY_MS, MAX_TRACE_ENTRIES, APPROVAL_EXIT_TIMEOUT_MS, CliStateEngine;
5162
+ var SCRIPT_STATUS_DEBOUNCE_MS, MAX_FINISH_RETRIES, FINISH_RETRY_DELAY_MS, MAX_TRACE_ENTRIES, APPROVAL_EXIT_TIMEOUT_MS, IDLE_CONFIRMATION_GRACE_MS, CliStateEngine;
5148
5163
  var init_cli_state_engine = __esm({
5149
5164
  "src/cli-adapters/cli-state-engine.ts"() {
5150
5165
  "use strict";
@@ -5156,6 +5171,7 @@ var init_cli_state_engine = __esm({
5156
5171
  FINISH_RETRY_DELAY_MS = 300;
5157
5172
  MAX_TRACE_ENTRIES = 250;
5158
5173
  APPROVAL_EXIT_TIMEOUT_MS = 6e4;
5174
+ IDLE_CONFIRMATION_GRACE_MS = 2e3;
5159
5175
  CliStateEngine = class {
5160
5176
  constructor(provider, runner, transport, callbacks, timeouts) {
5161
5177
  this.provider = provider;
@@ -5194,6 +5210,20 @@ var init_cli_state_engine = __esm({
5194
5210
  pendingScriptStatusTimer = null;
5195
5211
  // ── Idle candidate ───────────────────────────────
5196
5212
  idleFinishCandidate = null;
5213
+ // ── Idle confirmation grace ──────────────────────
5214
+ /**
5215
+ * `finishResponse` produces the `generating → idle` transition that
5216
+ * coordinators interpret as "task complete". Some providers (antigravity-
5217
+ * cli observed in the wild) briefly paint a screen that looks like an
5218
+ * idle prompt between tool result frames while still actively running,
5219
+ * which fired `response_finished` and broke completion semantics.
5220
+ * We defer the actual idle transition by IDLE_CONFIRMATION_GRACE_MS and
5221
+ * cancel it if the scripted detection re-detects generating during that
5222
+ * window — a true completion stays idle for many seconds, so a 2-second
5223
+ * grace is sufficient to filter the paint blip.
5224
+ */
5225
+ pendingIdleFinishTimer = null;
5226
+ pendingIdleFinishAt = 0;
5197
5227
  // ── Status history (debug) ───────────────────────
5198
5228
  statusHistory = [];
5199
5229
  traceEntries = [];
@@ -5368,6 +5398,11 @@ var init_cli_state_engine = __esm({
5368
5398
  clearTimeout(this.providerErrorRetryTimer);
5369
5399
  this.providerErrorRetryTimer = null;
5370
5400
  }
5401
+ if (this.pendingIdleFinishTimer) {
5402
+ clearTimeout(this.pendingIdleFinishTimer);
5403
+ this.pendingIdleFinishTimer = null;
5404
+ this.pendingIdleFinishAt = 0;
5405
+ }
5371
5406
  this.providerErrorRetryKey = "";
5372
5407
  }
5373
5408
  resetActiveTurnState() {
@@ -5511,7 +5546,7 @@ var init_cli_state_engine = __esm({
5511
5546
  "CLI",
5512
5547
  `[${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)}`
5513
5548
  );
5514
- const shouldHoldGenerating = status === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(parsedStatus === "idle" && !!lastParsedAssistant);
5549
+ const shouldHoldGenerating = status === "idle" && this.isWaitingForResponse && !!this.currentTurnScope && !modal && recentInteractiveActivity && !(parsedStatus === "idle" && !!lastParsedAssistant);
5515
5550
  if (shouldHoldGenerating) {
5516
5551
  this.applyHoldGenerating(ctx);
5517
5552
  return;
@@ -5607,19 +5642,30 @@ var init_cli_state_engine = __esm({
5607
5642
  if (!inCooldown) {
5608
5643
  if (!modal) {
5609
5644
  LOG.warn("CLI", `[${this.provider.type}] detectStatus=waiting_approval but parseApproval returned null; ignoring`);
5645
+ if (this.currentStatus === "waiting_approval") {
5646
+ this.activeModal = null;
5647
+ this.setStatus("generating", "approval_lost_modal");
5648
+ this.callbacks.onStatusChange();
5649
+ }
5610
5650
  return;
5611
5651
  }
5612
5652
  this.isWaitingForResponse = true;
5613
5653
  this.setStatus("waiting_approval", "script_detect");
5614
- this.activeModal = modal;
5654
+ const prev = this.activeModal;
5655
+ const prevBtnCount = Array.isArray(prev?.buttons) ? prev.buttons.length : 0;
5656
+ const nextBtnCount = Array.isArray(modal.buttons) ? modal.buttons.length : 0;
5657
+ if (!prev || prevBtnCount !== nextBtnCount) {
5658
+ this.activeModal = modal;
5659
+ this.callbacks.onStatusChange();
5660
+ }
5615
5661
  if (this.idleTimeout) clearTimeout(this.idleTimeout);
5616
5662
  this.armApprovalExitTimeout();
5617
- this.callbacks.onStatusChange();
5618
5663
  }
5619
5664
  }
5620
5665
  applyGenerating(ctx) {
5621
5666
  const { modal, parsedMessages, lastParsedAssistant, parsedStatus, prevStatus } = ctx;
5622
5667
  this.clearIdleFinishCandidate("generating");
5668
+ this.cancelPendingIdleFinish("generating_signal_returned");
5623
5669
  const snap = this.transport.getSnapshot();
5624
5670
  const effectiveScreenText = snap.screenText || snap.accumulatedBuffer;
5625
5671
  const noActiveTurn = !this.currentTurnScope;
@@ -5780,10 +5826,27 @@ var init_cli_state_engine = __esm({
5780
5826
  }
5781
5827
  this.resetActiveTurnState();
5782
5828
  this.callbacks.onTurnCompleted();
5783
- this.setStatus("idle", "response_finished");
5784
- this.callbacks.onStatusChange();
5829
+ this.scheduleIdleFinish("response_finished");
5785
5830
  this.transport.flushOutboundQueue();
5786
5831
  }
5832
+ scheduleIdleFinish(reason) {
5833
+ if (this.pendingIdleFinishTimer) clearTimeout(this.pendingIdleFinishTimer);
5834
+ this.pendingIdleFinishAt = Date.now() + IDLE_CONFIRMATION_GRACE_MS;
5835
+ this.pendingIdleFinishTimer = setTimeout(() => {
5836
+ this.pendingIdleFinishTimer = null;
5837
+ this.pendingIdleFinishAt = 0;
5838
+ if (this.isWaitingForResponse) return;
5839
+ this.setStatus("idle", reason);
5840
+ this.callbacks.onStatusChange();
5841
+ }, IDLE_CONFIRMATION_GRACE_MS);
5842
+ }
5843
+ cancelPendingIdleFinish(reason) {
5844
+ if (!this.pendingIdleFinishTimer) return;
5845
+ clearTimeout(this.pendingIdleFinishTimer);
5846
+ this.pendingIdleFinishTimer = null;
5847
+ this.pendingIdleFinishAt = 0;
5848
+ this.recordTrace("idle_finish_cancelled", { trigger: reason });
5849
+ }
5787
5850
  // ─── Helpers ────────────────────────────────────────────────────────────
5788
5851
  armApprovalExitTimeout() {
5789
5852
  if (this.approvalExitTimeout) clearTimeout(this.approvalExitTimeout);
@@ -6219,9 +6282,10 @@ var init_provider_cli_adapter = __esm({
6219
6282
  submitRetryTimer = null;
6220
6283
  // Resize redraw suppression
6221
6284
  resizeSuppressUntil = 0;
6222
- // Native transcript anchor when >0, native history was confirmed for this session.
6223
- // Prevents freshEnough flips caused by PTY buffer activity after the first successful native read.
6224
- nativeHistoryAnchoredAt = 0;
6285
+ // (A2.2) Native transcript anchor moved to CHAT_SOURCE_REGISTRY.
6286
+ // ChatSourceMachine holds the lock by state, not by a mutable field on
6287
+ // the adapter. Removed entirely; no callers remain after the readChat
6288
+ // ladder was replaced.
6225
6289
  // ─── Script runner (parsing isolated here, adapter stays as transport) ───
6226
6290
  runner;
6227
6291
  /** @deprecated use runner.cliScripts for direct script access */
@@ -6557,6 +6621,8 @@ ${lastSnapshot}`;
6557
6621
  this.engine.lastApprovalResolvedAt = Date.now();
6558
6622
  }
6559
6623
  this.engine.activeModal = null;
6624
+ this.engine.isWaitingForResponse = false;
6625
+ this.engine.currentTurnScope = null;
6560
6626
  this.engine.setStatus("idle", `startup_ready:${trigger}`);
6561
6627
  }
6562
6628
  LOG.info(
@@ -6649,7 +6715,8 @@ ${lastSnapshot}`;
6649
6715
  partialResponse: this.responseBuffer,
6650
6716
  isWaitingForResponse: this.engine.isWaitingForResponse,
6651
6717
  scope: this.engine.currentTurnScope,
6652
- runtimeSettings: this.runtimeSettings
6718
+ runtimeSettings: this.runtimeSettings,
6719
+ spawnAt: this.spawnAt
6653
6720
  });
6654
6721
  const session = this.runner.parseSession({
6655
6722
  ...input,
@@ -6686,7 +6753,7 @@ ${lastSnapshot}`;
6686
6753
  }
6687
6754
  applyParsedSessionMetadata(parsed) {
6688
6755
  const providerSessionId = typeof parsed?.providerSessionId === "string" && parsed.providerSessionId.trim() ? parsed.providerSessionId.trim() : "";
6689
- if (providerSessionId) {
6756
+ if (providerSessionId && providerSessionId !== this.providerSessionId) {
6690
6757
  this.providerSessionId = providerSessionId;
6691
6758
  this.updateRuntimeMeta({ providerSessionId });
6692
6759
  }
@@ -6704,7 +6771,25 @@ ${lastSnapshot}`;
6704
6771
  const startupDetectedStatus = allowParse && this.startupParseGate && !startupModal ? this.runDetectStatus(this.recentOutputBuffer || this.terminalScreen.getText()) : null;
6705
6772
  let effectiveStatus = this.projectEffectiveStatus(startupModal);
6706
6773
  let effectiveModal = startupModal || this.engine.activeModal;
6707
- if (startupDetectedStatus === "waiting_approval") {
6774
+ if (allowParse && !effectiveModal && this.engine.isWaitingForResponse) {
6775
+ const liveDetect = this.runDetectStatus(this.recentOutputBuffer || this.terminalScreen.getText());
6776
+ if (liveDetect === "waiting_approval") {
6777
+ const liveModal = this.runParseApproval(this.terminalScreen.getText()) || this.runParseApproval(this.recentOutputBuffer);
6778
+ if (liveModal) {
6779
+ effectiveModal = liveModal;
6780
+ if (!this.engine.activeModal) this.engine.activeModal = liveModal;
6781
+ } else {
6782
+ 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})`);
6783
+ }
6784
+ } else if (liveDetect && liveDetect !== "generating" && liveDetect !== "idle") {
6785
+ LOG.warn("CLI", `[${this.cliType}] getStatus live re-extract: detect=${liveDetect} (not waiting_approval)`);
6786
+ } else if (this.engine.currentStatus === "waiting_approval" && liveDetect !== "waiting_approval") {
6787
+ LOG.warn("CLI", `[${this.cliType}] getStatus live re-extract: engine.status=waiting_approval but live detect=${liveDetect}`);
6788
+ }
6789
+ } else if (!effectiveModal && this.engine.currentStatus === "waiting_approval") {
6790
+ LOG.warn("CLI", `[${this.cliType}] getStatus skipped live re-extract: allowParse=${allowParse} isWaitingForResponse=${this.engine.isWaitingForResponse}`);
6791
+ }
6792
+ if (startupDetectedStatus === "waiting_approval" && effectiveModal) {
6708
6793
  effectiveStatus = "waiting_approval";
6709
6794
  } else if (startupDetectedStatus === "idle" && !startupModal && !effectiveModal) {
6710
6795
  effectiveStatus = "idle";
@@ -6806,7 +6891,8 @@ ${lastSnapshot}`;
6806
6891
  partialResponse: this.responseBuffer,
6807
6892
  isWaitingForResponse: this.engine.isWaitingForResponse,
6808
6893
  scope: this.engine.currentTurnScope,
6809
- runtimeSettings: this.runtimeSettings
6894
+ runtimeSettings: this.runtimeSettings,
6895
+ spawnAt: this.spawnAt
6810
6896
  });
6811
6897
  return await Promise.resolve(this.runner.invokeByName(scriptName, {
6812
6898
  ...input,
@@ -14577,19 +14663,37 @@ function getProviderNativeHistoryScript(scripts, canonicalHistory, key) {
14577
14663
  function normalizeProviderNativeHistoryRecords(agentType, historySessionId, records) {
14578
14664
  if (!Array.isArray(records)) return [];
14579
14665
  const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
14580
- return records.map((record) => sanitizeHistoryMessage(agentType, {
14581
- ts: typeof record?.ts === "string" ? record.ts : new Date(Number(record?.receivedAt) || Date.now()).toISOString(),
14582
- receivedAt: Number(record?.receivedAt) || Date.parse(record?.ts || "") || Date.now(),
14583
- role: record?.role,
14584
- content: String(record?.content || ""),
14585
- kind: record?.kind || (record?.role === "system" ? "session_start" : "standard"),
14586
- senderName: record?.senderName,
14587
- agent: agentType,
14588
- instanceId: record?.instanceId,
14589
- historySessionId: normalizeSavedHistorySessionId(record?.historySessionId || normalizedSessionId),
14590
- sessionTitle: record?.sessionTitle,
14591
- workspace: record?.workspace
14592
- })).filter(Boolean);
14666
+ return records.map((record) => {
14667
+ const base = {
14668
+ ts: typeof record?.ts === "string" ? record.ts : new Date(Number(record?.receivedAt) || Date.now()).toISOString(),
14669
+ receivedAt: Number(record?.receivedAt) || Date.parse(record?.ts || "") || Date.now(),
14670
+ role: record?.role,
14671
+ content: String(record?.content || ""),
14672
+ kind: record?.kind || (record?.role === "system" ? "session_start" : "standard"),
14673
+ senderName: record?.senderName,
14674
+ agent: agentType,
14675
+ instanceId: record?.instanceId,
14676
+ historySessionId: normalizeSavedHistorySessionId(record?.historySessionId || normalizedSessionId),
14677
+ sessionTitle: record?.sessionTitle,
14678
+ workspace: record?.workspace
14679
+ };
14680
+ if (typeof record?.providerUnitKey === "string" && record.providerUnitKey) {
14681
+ base.providerUnitKey = record.providerUnitKey;
14682
+ }
14683
+ if (typeof record?.bubbleId === "string" && record.bubbleId) {
14684
+ base.bubbleId = record.bubbleId;
14685
+ }
14686
+ if (typeof record?.sequence === "number" && Number.isFinite(record.sequence)) {
14687
+ base.sequence = record.sequence;
14688
+ }
14689
+ if (typeof record?._turnKey === "string" && record._turnKey) {
14690
+ base._turnKey = record._turnKey;
14691
+ }
14692
+ if (typeof record?.bubbleState === "string" && record.bubbleState) {
14693
+ base.bubbleState = record.bubbleState;
14694
+ }
14695
+ return sanitizeHistoryMessage(agentType, base);
14696
+ }).filter(Boolean);
14593
14697
  }
14594
14698
  function callProviderNativeHistoryRead(agentType, canonicalHistory, scripts, historySessionId, workspace, excludeInProgressTurn) {
14595
14699
  const fn = getProviderNativeHistoryScript(scripts, canonicalHistory, "readSession");
@@ -15254,6 +15358,9 @@ ${effect.notification.body || ""}`.trim();
15254
15358
  // src/providers/ide-provider-instance.ts
15255
15359
  init_logger();
15256
15360
 
15361
+ // src/providers/transcript-v2.ts
15362
+ var CHAT_CONTRACT_VERSION_V1 = "1.0";
15363
+
15257
15364
  // src/providers/read-chat-contract.ts
15258
15365
  var VALID_STATUSES = ["idle", "generating", "waiting_approval", "error", "panel_hidden", "starting", "streaming", "long_generating"];
15259
15366
  var VALID_ROLES = ["user", "assistant", "system", "human"];
@@ -15310,6 +15417,7 @@ function validateMessage(message, source, index) {
15310
15417
  if (isFiniteNumber(message.index)) normalized.index = message.index;
15311
15418
  if (isFiniteNumber(message.timestamp)) normalized.timestamp = message.timestamp;
15312
15419
  if (isFiniteNumber(message.receivedAt)) normalized.receivedAt = message.receivedAt;
15420
+ if (isFiniteNumber(message.sequence)) normalized.sequence = message.sequence;
15313
15421
  if (typeof message._turnKey === "string") normalized._turnKey = message._turnKey;
15314
15422
  if (Array.isArray(message.toolCalls)) normalized.toolCalls = message.toolCalls;
15315
15423
  if (isPlainObject3(message.meta)) normalized.meta = message.meta;
@@ -17241,12 +17349,365 @@ function buildSessionModalDeliverySignature(payload) {
17241
17349
  ]);
17242
17350
  }
17243
17351
 
17352
+ // src/chat/source-machine.ts
17353
+ var INITIAL_CHAT_SOURCE_STATE = Object.freeze({
17354
+ name: "Booting",
17355
+ nativeSequencePeak: void 0,
17356
+ committedUnitKeys: Object.freeze(/* @__PURE__ */ new Set()),
17357
+ recoveringMisses: 0
17358
+ });
17359
+ var RECOVERING_MISS_PROMOTION_THRESHOLD = 3;
17360
+ function transitionChatSourceState(prev, observation, at, lockedSince) {
17361
+ const fromState = prev.name;
17362
+ if (observation.kind === "native_unavailable") {
17363
+ return handleNativeUnavailable(prev, observation.reason, at, lockedSince);
17364
+ }
17365
+ return handleNativePresent(prev, observation, at, lockedSince, fromState);
17366
+ }
17367
+ function handleNativeUnavailable(prev, reason, at, lockedSince) {
17368
+ const cause = reasonToUnavailableCause(reason);
17369
+ const fromState = prev.name;
17370
+ if (prev.name === "Booting") {
17371
+ const next2 = {
17372
+ name: "PtyOnly",
17373
+ nativeSequencePeak: void 0,
17374
+ committedUnitKeys: prev.committedUnitKeys,
17375
+ recoveringMisses: 0
17376
+ };
17377
+ return {
17378
+ next: next2,
17379
+ selected: "pty-parser",
17380
+ transition: { fromState, toState: "PtyOnly", event: "NativeUnavailable", cause, at },
17381
+ lockState: { locked: false }
17382
+ };
17383
+ }
17384
+ if (prev.name === "PtyOnly") {
17385
+ return {
17386
+ next: prev,
17387
+ selected: "pty-parser",
17388
+ transition: { fromState, toState: "PtyOnly", event: "NoOp", cause, at },
17389
+ lockState: { locked: false }
17390
+ };
17391
+ }
17392
+ if (prev.name === "NativeLocked") {
17393
+ const next2 = {
17394
+ name: "Recovering",
17395
+ nativeSequencePeak: prev.nativeSequencePeak,
17396
+ committedUnitKeys: prev.committedUnitKeys,
17397
+ recoveringMisses: 1
17398
+ };
17399
+ return {
17400
+ next: next2,
17401
+ selected: "pty-parser",
17402
+ transition: { fromState, toState: "Recovering", event: "NativeUnavailable", cause, at },
17403
+ lockState: { locked: false }
17404
+ };
17405
+ }
17406
+ const misses = prev.recoveringMisses + 1;
17407
+ if (misses >= RECOVERING_MISS_PROMOTION_THRESHOLD) {
17408
+ const next2 = {
17409
+ name: "PtyOnly",
17410
+ nativeSequencePeak: prev.nativeSequencePeak,
17411
+ committedUnitKeys: prev.committedUnitKeys,
17412
+ recoveringMisses: 0
17413
+ };
17414
+ return {
17415
+ next: next2,
17416
+ selected: "pty-parser",
17417
+ transition: { fromState, toState: "PtyOnly", event: "NativeUnavailable", cause, at },
17418
+ lockState: { locked: false }
17419
+ };
17420
+ }
17421
+ const next = {
17422
+ name: "Recovering",
17423
+ nativeSequencePeak: prev.nativeSequencePeak,
17424
+ committedUnitKeys: prev.committedUnitKeys,
17425
+ recoveringMisses: misses
17426
+ };
17427
+ return {
17428
+ next,
17429
+ selected: "pty-parser",
17430
+ transition: { fromState, toState: "Recovering", event: "NoOp", cause, at },
17431
+ lockState: { locked: false }
17432
+ };
17433
+ }
17434
+ function handleNativePresent(prev, observation, at, lockedSince, fromState) {
17435
+ if (!observation.safeMapping) {
17436
+ return regressTo(prev, fromState, "native_regressed_unsafe_mapping", at);
17437
+ }
17438
+ if (observation.coverage === "partial" && observation.messages.length === 0) {
17439
+ return regressTo(prev, fromState, "native_regressed_coverage_partial", at);
17440
+ }
17441
+ if (observation.messages.length === 0) {
17442
+ return handleNativeUnavailable(prev, "empty", at, lockedSince);
17443
+ }
17444
+ const incomingUnitKeys = collectUnitKeys(observation.messages);
17445
+ const incomingPeak = maxSequence(observation.messages);
17446
+ if (prev.name === "Booting") {
17447
+ if (observation.coverage === "partial") {
17448
+ const next2 = {
17449
+ name: "Recovering",
17450
+ nativeSequencePeak: incomingPeak,
17451
+ committedUnitKeys: incomingUnitKeys,
17452
+ recoveringMisses: 0
17453
+ };
17454
+ return {
17455
+ next: next2,
17456
+ selected: "pty-parser",
17457
+ transition: { fromState, toState: "Recovering", event: "NativeProgressed", cause: "native_progressed", at },
17458
+ lockState: { locked: false }
17459
+ };
17460
+ }
17461
+ const next = {
17462
+ name: "NativeLocked",
17463
+ nativeSequencePeak: incomingPeak,
17464
+ committedUnitKeys: incomingUnitKeys,
17465
+ recoveringMisses: 0
17466
+ };
17467
+ return {
17468
+ next,
17469
+ selected: "native-history",
17470
+ transition: { fromState, toState: "NativeLocked", event: "NativeProgressed", cause: "native_progressed", at },
17471
+ lockState: { locked: true, lockedSince: at }
17472
+ };
17473
+ }
17474
+ if (prev.name === "NativeLocked") {
17475
+ if (!isSupersetOf(incomingUnitKeys, prev.committedUnitKeys)) {
17476
+ return regressTo(prev, fromState, "native_regressed_shrunk", at);
17477
+ }
17478
+ if (prev.nativeSequencePeak !== void 0 && incomingPeak < prev.nativeSequencePeak) {
17479
+ return regressTo(prev, fromState, "native_regressed_shrunk", at);
17480
+ }
17481
+ const next = {
17482
+ name: "NativeLocked",
17483
+ nativeSequencePeak: Math.max(prev.nativeSequencePeak ?? incomingPeak, incomingPeak),
17484
+ committedUnitKeys: incomingUnitKeys,
17485
+ recoveringMisses: 0
17486
+ };
17487
+ return {
17488
+ next,
17489
+ selected: "native-history",
17490
+ transition: { fromState, toState: "NativeLocked", event: "NoOp", cause: "native_progressed", at },
17491
+ lockState: { locked: true, lockedSince: lockedSince ?? at }
17492
+ };
17493
+ }
17494
+ if (prev.name === "Recovering") {
17495
+ const meetsWatermark = prev.nativeSequencePeak === void 0 || incomingPeak >= prev.nativeSequencePeak;
17496
+ if (meetsWatermark && isSupersetOf(incomingUnitKeys, prev.committedUnitKeys) && observation.coverage !== "partial") {
17497
+ const next = {
17498
+ name: "NativeLocked",
17499
+ nativeSequencePeak: Math.max(prev.nativeSequencePeak ?? incomingPeak, incomingPeak),
17500
+ committedUnitKeys: incomingUnitKeys,
17501
+ recoveringMisses: 0
17502
+ };
17503
+ return {
17504
+ next,
17505
+ selected: "native-history",
17506
+ transition: { fromState, toState: "NativeLocked", event: "NativeProgressed", cause: "native_progressed", at },
17507
+ lockState: { locked: true, lockedSince: at }
17508
+ };
17509
+ }
17510
+ return handleNativeUnavailable(prev, "empty", at, lockedSince);
17511
+ }
17512
+ if (prev.nativeSequencePeak === void 0 || incomingPeak > prev.nativeSequencePeak) {
17513
+ if (observation.coverage !== "partial" && incomingUnitKeys.size > 0) {
17514
+ const next = {
17515
+ name: "NativeLocked",
17516
+ nativeSequencePeak: Math.max(prev.nativeSequencePeak ?? incomingPeak, incomingPeak),
17517
+ committedUnitKeys: incomingUnitKeys,
17518
+ recoveringMisses: 0
17519
+ };
17520
+ return {
17521
+ next,
17522
+ selected: "native-history",
17523
+ transition: { fromState, toState: "NativeLocked", event: "NativeProgressed", cause: "native_progressed", at },
17524
+ lockState: { locked: true, lockedSince: at }
17525
+ };
17526
+ }
17527
+ } else if (incomingPeak >= prev.nativeSequencePeak) {
17528
+ if (isSupersetOf(incomingUnitKeys, prev.committedUnitKeys) && observation.coverage !== "partial") {
17529
+ const next = {
17530
+ name: "NativeLocked",
17531
+ nativeSequencePeak: Math.max(prev.nativeSequencePeak ?? incomingPeak, incomingPeak),
17532
+ committedUnitKeys: incomingUnitKeys,
17533
+ recoveringMisses: 0
17534
+ };
17535
+ return {
17536
+ next,
17537
+ selected: "native-history",
17538
+ transition: { fromState, toState: "NativeLocked", event: "NativeProgressed", cause: "native_progressed", at },
17539
+ lockState: { locked: true, lockedSince: at }
17540
+ };
17541
+ }
17542
+ }
17543
+ return {
17544
+ next: prev,
17545
+ selected: "pty-parser",
17546
+ transition: { fromState, toState: "PtyOnly", event: "NoOp", cause: "native_progressed", at },
17547
+ lockState: { locked: false }
17548
+ };
17549
+ }
17550
+ function regressTo(prev, fromState, cause, at) {
17551
+ const next = {
17552
+ name: "PtyOnly",
17553
+ nativeSequencePeak: prev.nativeSequencePeak,
17554
+ committedUnitKeys: prev.committedUnitKeys,
17555
+ recoveringMisses: 0
17556
+ };
17557
+ return {
17558
+ next,
17559
+ selected: "pty-parser",
17560
+ transition: { fromState, toState: "PtyOnly", event: "NativeRegressed", cause, at },
17561
+ lockState: { locked: false }
17562
+ };
17563
+ }
17564
+ function reasonToUnavailableCause(reason) {
17565
+ switch (reason) {
17566
+ case "provider_not_supported":
17567
+ return "native_unavailable_provider_unsupported";
17568
+ case "read_error":
17569
+ return "native_unavailable_read_error";
17570
+ case "empty":
17571
+ return "native_unavailable_empty";
17572
+ case "not_native_source":
17573
+ return "native_unavailable_not_native_source";
17574
+ case "coverage_unavailable":
17575
+ return "native_regressed_coverage_unavailable";
17576
+ }
17577
+ }
17578
+ function collectUnitKeys(messages) {
17579
+ const set = /* @__PURE__ */ new Set();
17580
+ for (const m of messages) set.add(m.providerUnitKey);
17581
+ return set;
17582
+ }
17583
+ function maxSequence(messages) {
17584
+ let max = -Infinity;
17585
+ for (const m of messages) {
17586
+ if (m.sequence > max) max = m.sequence;
17587
+ }
17588
+ return max === -Infinity ? 0 : max;
17589
+ }
17590
+ function isSupersetOf(candidate, required) {
17591
+ if (required.size === 0) return true;
17592
+ for (const key of required) {
17593
+ if (!candidate.has(key)) return false;
17594
+ }
17595
+ return true;
17596
+ }
17597
+
17598
+ // src/chat/source-resolver.ts
17599
+ var TRANSITION_HISTORY_LIMIT = 25;
17600
+ function chatSourceSessionKey(providerType, sessionId) {
17601
+ return `${providerType}\0${sessionId}`;
17602
+ }
17603
+ var ChatSourceRegistry = class {
17604
+ records = /* @__PURE__ */ new Map();
17605
+ /** Snapshot of current state for diagnostics. Does not mutate. */
17606
+ getState(key) {
17607
+ return this.records.get(key)?.state ?? INITIAL_CHAT_SOURCE_STATE;
17608
+ }
17609
+ /** Recent transitions, newest last. Empty array when nothing has happened. */
17610
+ getTransitions(key) {
17611
+ return this.records.get(key)?.transitions ?? [];
17612
+ }
17613
+ /** Drop a session. Caller should invoke this when the session is destroyed
17614
+ * to avoid unbounded growth across long-lived daemons. */
17615
+ clear(key) {
17616
+ this.records.delete(key);
17617
+ }
17618
+ /** Drop all sessions. Test helper. */
17619
+ clearAll() {
17620
+ this.records.clear();
17621
+ }
17622
+ /**
17623
+ * Apply one observation, returning the decision and side-effecting the
17624
+ * stored state. The returned `nextState` is the same object now stored
17625
+ * under `key`; callers may treat the decision as authoritative without
17626
+ * re-reading.
17627
+ */
17628
+ observe(key, observation, at = Date.now()) {
17629
+ const prev = this.records.get(key);
17630
+ const prevState = prev?.state ?? INITIAL_CHAT_SOURCE_STATE;
17631
+ const prevLockedSince = prev?.lockedSince;
17632
+ const result = transitionChatSourceState(prevState, observation, at, prevLockedSince);
17633
+ const transitions = prev?.transitions ?? [];
17634
+ const nextTransitions = appendTransition(transitions, result.transition);
17635
+ const lockedSince = result.lockState.lockedSince;
17636
+ this.records.set(key, {
17637
+ state: result.next,
17638
+ lockedSince,
17639
+ transitions: nextTransitions
17640
+ });
17641
+ return {
17642
+ selected: result.selected,
17643
+ nextState: result.next,
17644
+ transition: result.transition,
17645
+ lockState: result.lockState
17646
+ };
17647
+ }
17648
+ };
17649
+ function appendTransition(existing, next) {
17650
+ const last = existing[existing.length - 1];
17651
+ if (last && last.fromState === next.fromState && last.toState === next.toState && last.event === next.event && last.cause === next.cause) {
17652
+ return existing;
17653
+ }
17654
+ const trimmed = existing.length >= TRANSITION_HISTORY_LIMIT ? existing.slice(existing.length - TRANSITION_HISTORY_LIMIT + 1) : [...existing];
17655
+ trimmed.push(next);
17656
+ return trimmed;
17657
+ }
17658
+ function buildV1NativePresentObservation(args) {
17659
+ const identities = [];
17660
+ let synthesisedSequence = 0;
17661
+ for (const message of args.messages) {
17662
+ const providerUnitKey = pickFirstString(
17663
+ message.providerUnitKey,
17664
+ message.bubbleId,
17665
+ message.id
17666
+ ) ?? synthesiseV1UnitKey(args.providerType, args.sessionId, synthesisedSequence, message);
17667
+ const sequence = pickFiniteNumber(message.receivedAt, message.timestamp, message.index) ?? synthesisedSequence;
17668
+ identities.push({ providerUnitKey, sequence });
17669
+ synthesisedSequence += 1;
17670
+ }
17671
+ return {
17672
+ kind: "native_present",
17673
+ contractVersion: CHAT_CONTRACT_VERSION_V1,
17674
+ messages: identities,
17675
+ coverage: args.coverage,
17676
+ safeMapping: args.safeMapping
17677
+ };
17678
+ }
17679
+ function pickFirstString(...candidates) {
17680
+ for (const c of candidates) {
17681
+ if (typeof c === "string" && c.length > 0) return c;
17682
+ }
17683
+ return void 0;
17684
+ }
17685
+ function pickFiniteNumber(...candidates) {
17686
+ for (const c of candidates) {
17687
+ if (typeof c === "number" && Number.isFinite(c)) return c;
17688
+ }
17689
+ return void 0;
17690
+ }
17691
+ function synthesiseV1UnitKey(providerType, sessionId, positionalSeq, message) {
17692
+ const role = typeof message.role === "string" ? message.role : "";
17693
+ const ts2 = pickFiniteNumber(message.receivedAt, message.timestamp);
17694
+ return `v1:${providerType}:${sessionId}:${ts2 ?? ""}:${positionalSeq}:${role}`;
17695
+ }
17696
+ var CHAT_SOURCE_REGISTRY = new ChatSourceRegistry();
17697
+
17244
17698
  // src/commands/chat-commands.ts
17245
17699
  var RECENT_SEND_WINDOW_MS = 1200;
17246
17700
  var READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25e3;
17247
17701
  var HERMES_CLI_STARTING_SEND_SETTLE_MS = 2e3;
17248
- var CLI_NATIVE_HISTORY_FRESH_MS = 5 * 6e4;
17249
17702
  var CLI_NATIVE_TRANSCRIPT_PROVIDERS = /* @__PURE__ */ new Set(["codex-cli", "claude-cli", "hermes-cli", "antigravity-cli"]);
17703
+ var warnedLegacyNativeAllowlistHits = /* @__PURE__ */ new Set();
17704
+ function warnLegacyNativeAllowlistHit(providerType) {
17705
+ if (warnedLegacyNativeAllowlistHits.has(providerType)) return;
17706
+ warnedLegacyNativeAllowlistHits.add(providerType);
17707
+ console.warn(
17708
+ `[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.`
17709
+ );
17710
+ }
17250
17711
  var recentSendByTarget = /* @__PURE__ */ new Map();
17251
17712
  function getCurrentProviderType(h, fallback = "") {
17252
17713
  return h.currentSession?.providerType || h.currentProviderType || fallback;
@@ -17421,7 +17882,11 @@ function readHistorySessionIdFromMessages(messages) {
17421
17882
  function shouldPreserveNativeIdentity(providerType, sessionId, message) {
17422
17883
  const providerUnitKey = typeof message.providerUnitKey === "string" ? message.providerUnitKey.trim() : "";
17423
17884
  const turnKey = typeof message._turnKey === "string" ? message._turnKey.trim() : "";
17424
- if (!providerUnitKey || !turnKey) return false;
17885
+ if (!providerUnitKey) return false;
17886
+ if (providerUnitKey.startsWith("v2:") || providerUnitKey.startsWith("v2-pty:")) {
17887
+ return true;
17888
+ }
17889
+ if (!turnKey) return false;
17425
17890
  if (providerType === "hermes-cli" && sessionId) {
17426
17891
  return providerUnitKey.startsWith(`${providerType}:native:${sessionId}:`) && turnKey.startsWith(`${providerType}:native-turn:${sessionId}:`);
17427
17892
  }
@@ -17450,12 +17915,16 @@ function normalizeNativeHistoryMessages(providerType, messages, nativeSessionId)
17450
17915
  const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
17451
17916
  const isSystemSessionStart = role === "system" || kind === "system" || kind === "session_start";
17452
17917
  const isActivity = role === "assistant" && (kind === "tool" || kind === "terminal" || kind === "thought");
17918
+ const existingSequence = typeof message.sequence === "number" && Number.isFinite(message.sequence) ? message.sequence : null;
17919
+ const tsCandidate = Number(message.receivedAt || message.timestamp || 0);
17920
+ const sequence = existingSequence !== null ? existingSequence : tsCandidate > 0 ? tsCandidate : index;
17453
17921
  return {
17454
17922
  ...message,
17455
17923
  role: role === "human" ? "user" : role || "assistant",
17456
17924
  kind: isSystemSessionStart ? "system" : kind,
17457
17925
  providerUnitKey,
17458
17926
  bubbleId: typeof message.bubbleId === "string" && message.bubbleId.trim() && preserveNativeIdentity ? message.bubbleId.trim() : `bubble:${providerUnitKey}`,
17927
+ sequence,
17459
17928
  _turnKey: preserveNativeIdentity ? existingTurnKey : `${providerType}:native-turn:${nativeIdentitySessionId || "workspace"}:${turnIndex}`,
17460
17929
  bubbleState: message.bubbleState || "final",
17461
17930
  ...isSystemSessionStart ? {
@@ -17514,17 +17983,185 @@ function buildCliMessageSourceProvenance(args) {
17514
17983
  }
17515
17984
  };
17516
17985
  }
17517
- function buildNativeHistoryFallbackReason(args) {
17518
- if (!supportsCliNativeTranscript(args.providerType, args.provider)) return "provider_native_transcript_not_supported";
17519
- if (args.unavailableReason) return `native_history_unavailable:${args.unavailableReason}`;
17520
- if (args.nativeSource === "native-unavailable") return "native_history_unavailable";
17521
- if (args.nativeHistoryCoverage === "partial") return "native_history_partial";
17522
- if (args.nativeHistoryCoverage === "unavailable") return "native_history_unavailable";
17523
- if (args.nativeSource && args.nativeSource !== "provider-native") return `native_history_source_${args.nativeSource}`;
17524
- if (args.nativeMessageCount <= 0) return "native_history_empty";
17525
- if (!args.safeMapping) return "native_history_not_safely_mapped";
17526
- if (!args.freshEnough) return "native_history_stale";
17527
- return "native_history_not_selected";
17986
+ function causeToLegacyFallbackReason(cause, selected, extraDetail) {
17987
+ if (selected === "native-history") return void 0;
17988
+ switch (cause) {
17989
+ case "initial":
17990
+ return "native_history_not_checked";
17991
+ case "native_progressed":
17992
+ return "native_history_not_selected";
17993
+ case "native_regressed_shrunk":
17994
+ return "native_history_empty";
17995
+ case "native_regressed_unsafe_mapping":
17996
+ return "native_history_not_safely_mapped";
17997
+ case "native_regressed_coverage_partial":
17998
+ return "native_history_partial";
17999
+ case "native_regressed_coverage_unavailable":
18000
+ return "native_history_unavailable";
18001
+ case "native_unavailable_read_error":
18002
+ return extraDetail?.unavailableReason ? `native_history_unavailable:${extraDetail.unavailableReason}` : "native_history_unavailable";
18003
+ case "native_unavailable_provider_unsupported":
18004
+ return "provider_native_transcript_not_supported";
18005
+ case "native_unavailable_empty":
18006
+ return "native_history_empty";
18007
+ case "native_unavailable_not_native_source":
18008
+ return extraDetail?.nativeSource ? `native_history_source_${extraDetail.nativeSource}` : "native_history_unavailable";
18009
+ }
18010
+ }
18011
+ function decideCliReadChatSource(args) {
18012
+ const supportsNative = supportsCliNativeTranscript(args.providerType, args.provider);
18013
+ const observation = buildObservationForCli(args, supportsNative);
18014
+ const sessionKey = chatSourceSessionKey(args.providerType, args.sessionId);
18015
+ const decision = CHAT_SOURCE_REGISTRY.observe(sessionKey, observation);
18016
+ const nativeMessages = observation.kind === "native_present" ? extractNativeMessagesFromResult(args.providerType, args.nativeHistoryResult) : [];
18017
+ const nativeSource = typeof args.nativeHistoryResult?.source === "string" ? args.nativeHistoryResult.source : void 0;
18018
+ const sourcePath = typeof args.nativeHistoryResult?.sourcePath === "string" ? args.nativeHistoryResult.sourcePath : void 0;
18019
+ const sourceMtimeMs = typeof args.nativeHistoryResult?.sourceMtimeMs === "number" ? args.nativeHistoryResult.sourceMtimeMs : void 0;
18020
+ const coverageHint = typeof args.nativeHistoryResult?.nativeHistoryCoverage === "string" ? args.nativeHistoryResult.nativeHistoryCoverage : void 0;
18021
+ const partialReason = typeof args.nativeHistoryResult?.partialReason === "string" ? args.nativeHistoryResult.partialReason : void 0;
18022
+ const unavailableReason = typeof args.nativeHistoryResult?.unavailableReason === "string" ? args.nativeHistoryResult.unavailableReason : args.nativeHistoryError ? `error:${args.nativeHistoryError?.message || String(args.nativeHistoryError)}` : void 0;
18023
+ const nativeHandle = typeof args.nativeHistoryResult?.providerSessionId === "string" ? args.nativeHistoryResult.providerSessionId : void 0;
18024
+ const transcriptWorkspace = typeof args.nativeHistoryResult?.workspace === "string" ? args.nativeHistoryResult.workspace : nativeMessages.map((m) => typeof m?.workspace === "string" ? m.workspace.trim() : "").find(Boolean);
18025
+ const fallbackReason = causeToLegacyFallbackReason(decision.transition.cause, decision.selected, {
18026
+ unavailableReason,
18027
+ nativeSource: nativeSource && nativeSource !== "provider-native" ? nativeSource : void 0
18028
+ });
18029
+ const ptyStatusApprovalOnly = decision.selected === "native-history" ? true : args.ptyStatusApprovalOnly;
18030
+ const messageSource = buildCliMessageSourceProvenance({
18031
+ selected: decision.selected,
18032
+ provider: args.providerType,
18033
+ nativeHandle,
18034
+ sessionWorkspace: args.sessionWorkspace,
18035
+ intendedWorkspace: args.intendedWorkspace,
18036
+ transcriptWorkspace,
18037
+ fallbackReason,
18038
+ nativeSource,
18039
+ sourcePath,
18040
+ sourceMtimeMs,
18041
+ nativeHistoryCoverage: coverageHint,
18042
+ partialReason,
18043
+ unavailableReason,
18044
+ nativeMessages,
18045
+ ptyMessages: args.ptyMessages,
18046
+ returnedMessages: decision.selected === "native-history" ? nativeMessages : args.ptyMessages,
18047
+ safeMapping: args.safeMapping,
18048
+ // freshEnough is a v1 concept the machine does not model directly.
18049
+ // We surface lockState.locked here so v1 consumers reading
18050
+ // staleness.freshEnough still get a meaningful boolean.
18051
+ freshEnough: decision.lockState.locked,
18052
+ ptyStatusApprovalOnly
18053
+ });
18054
+ return {
18055
+ decision,
18056
+ messageSource,
18057
+ nativeMessages,
18058
+ nativeSelected: decision.selected === "native-history"
18059
+ };
18060
+ }
18061
+ function buildObservationForCli(args, supportsNative) {
18062
+ if (!supportsNative) {
18063
+ return { kind: "native_unavailable", reason: "provider_not_supported" };
18064
+ }
18065
+ if (args.nativeHistoryError) {
18066
+ return { kind: "native_unavailable", reason: "read_error" };
18067
+ }
18068
+ const result = args.nativeHistoryResult;
18069
+ if (!result || typeof result !== "object") {
18070
+ return { kind: "native_unavailable", reason: "read_error" };
18071
+ }
18072
+ const source = typeof result.source === "string" ? result.source : "";
18073
+ if (source && source !== "provider-native") {
18074
+ return { kind: "native_unavailable", reason: source === "native-unavailable" ? "empty" : "not_native_source" };
18075
+ }
18076
+ const messages = Array.isArray(result.messages) ? result.messages : [];
18077
+ if (messages.length === 0) {
18078
+ return { kind: "native_unavailable", reason: "empty" };
18079
+ }
18080
+ const coverage = typeof result.nativeHistoryCoverage === "string" ? result.nativeHistoryCoverage : "tail";
18081
+ if (coverage === "unavailable") {
18082
+ return { kind: "native_unavailable", reason: "coverage_unavailable" };
18083
+ }
18084
+ return buildV1NativePresentObservation({
18085
+ providerType: args.providerType,
18086
+ sessionId: args.sessionId,
18087
+ messages,
18088
+ coverage: coverage === "full" || coverage === "tail" || coverage === "current-turn" || coverage === "partial" ? coverage : "tail",
18089
+ safeMapping: args.safeMapping
18090
+ });
18091
+ }
18092
+ function extractNativeMessagesFromResult(providerType, result) {
18093
+ if (!result || !Array.isArray(result.messages)) return [];
18094
+ return normalizeNativeHistoryMessages(
18095
+ providerType,
18096
+ result.messages,
18097
+ typeof result.providerSessionId === "string" ? result.providerSessionId : void 0
18098
+ );
18099
+ }
18100
+ function applyUnsafeNativeDaemonFallback(args) {
18101
+ if (args.adapter.cliType !== "codex-cli") {
18102
+ return;
18103
+ }
18104
+ const ms = args.messageSourceRef.get();
18105
+ const fallbackReason = typeof ms.fallbackReason === "string" ? ms.fallbackReason : "";
18106
+ if (!isUnsafeNativeTranscriptFallback(fallbackReason)) {
18107
+ return;
18108
+ }
18109
+ const safeCurrentRuntimePtyMessages = isCurrentRuntimePtySafelyAttributed({
18110
+ adapter: args.adapter,
18111
+ helpers: args.helpers,
18112
+ readChatArgs: args.readChatArgs,
18113
+ sessionWorkspace: args.sessionWorkspace,
18114
+ intendedWorkspace: args.intendedWorkspace,
18115
+ ptyMessages: args.ptyMessages
18116
+ });
18117
+ if (safeCurrentRuntimePtyMessages) {
18118
+ args.apply({
18119
+ messages: args.ptyMessages,
18120
+ transcriptAuthority: "daemon",
18121
+ coverage: args.coverage || "current-turn",
18122
+ status: args.returnedStatus
18123
+ });
18124
+ const next2 = { ...ms, selectedDaemonSource: "current-runtime-pty", transcriptAuthority: "daemon", runtimeMappingSafe: true };
18125
+ args.messageSourceRef.set(next2);
18126
+ return;
18127
+ }
18128
+ const safeRuntimeAckMessages = selectRuntimeInputAckMessages(args.ptyMessages);
18129
+ if (safeRuntimeAckMessages.length > 0) {
18130
+ args.apply({
18131
+ messages: safeRuntimeAckMessages,
18132
+ transcriptAuthority: "daemon",
18133
+ coverage: "tail",
18134
+ status: coerceUnsafeNativeFallbackStatus(args.returnedStatus, args.activeModal)
18135
+ });
18136
+ const next2 = { ...ms, ptyStatusApprovalOnly: true };
18137
+ args.messageSourceRef.set(next2);
18138
+ return;
18139
+ }
18140
+ const exactRuntimeMirrorMessages = readExactRuntimeMirrorMessages({
18141
+ providerType: args.providerType,
18142
+ targetSessionId: typeof args.readChatArgs?.targetSessionId === "string" ? args.readChatArgs.targetSessionId : void 0,
18143
+ currentSessionId: typeof args.helpers.currentSession?.sessionId === "string" ? args.helpers.currentSession.sessionId : void 0,
18144
+ tailLimit: args.nativeHistoryLimit,
18145
+ historyBehavior: args.provider?.historyBehavior
18146
+ });
18147
+ if (exactRuntimeMirrorMessages.length > 0) {
18148
+ args.apply({
18149
+ messages: exactRuntimeMirrorMessages,
18150
+ transcriptAuthority: "daemon",
18151
+ coverage: "tail",
18152
+ status: coerceUnsafeNativeFallbackStatus(args.returnedStatus, args.activeModal)
18153
+ });
18154
+ const next2 = { ...ms, selectedDaemonSource: "exact-runtime-mirror", transcriptAuthority: "daemon", ptyStatusApprovalOnly: true };
18155
+ args.messageSourceRef.set(next2);
18156
+ return;
18157
+ }
18158
+ args.apply({
18159
+ messages: args.ptyMessages,
18160
+ coverage: args.coverage,
18161
+ status: coerceUnsafeNativeFallbackStatus(args.returnedStatus, args.activeModal)
18162
+ });
18163
+ const next = { ...ms, ptyStatusApprovalOnly: true };
18164
+ args.messageSourceRef.set(next);
17528
18165
  }
17529
18166
  function isUnsafeNativeTranscriptFallback(reason) {
17530
18167
  const value = String(reason || "").trim();
@@ -17596,8 +18233,14 @@ function isCurrentRuntimePtySafelyAttributed(args) {
17596
18233
  return true;
17597
18234
  }
17598
18235
  function supportsCliNativeTranscript(providerType, provider) {
17599
- if (CLI_NATIVE_TRANSCRIPT_PROVIDERS.has(providerType)) return true;
17600
- return provider?.category === "cli" && isNativeSourceCanonicalHistory(provider?.canonicalHistory);
18236
+ if (provider?.category === "cli" && isNativeSourceCanonicalHistory(provider?.canonicalHistory)) {
18237
+ return true;
18238
+ }
18239
+ if (CLI_NATIVE_TRANSCRIPT_PROVIDERS.has(providerType)) {
18240
+ warnLegacyNativeAllowlistHit(providerType);
18241
+ return true;
18242
+ }
18243
+ return false;
17601
18244
  }
17602
18245
  function getComparableVisibleText(message) {
17603
18246
  if (!message) return "";
@@ -17696,14 +18339,6 @@ function readLiveCodexWorkspaceNativeHistory(agentStr, args) {
17696
18339
  });
17697
18340
  return { ...history, lookup: "workspace" };
17698
18341
  }
17699
- function isNativeHistoryFreshEnough(args) {
17700
- const nativeNewest = getMessageNewestReceivedAt(args.nativeMessages);
17701
- const ptyNewest = getMessageNewestReceivedAt(args.ptyMessages);
17702
- if (nativeNewest > 0 && nativeNewest >= ptyNewest) return true;
17703
- const sourceMtimeMs = Number(args.sourceMtimeMs || 0);
17704
- if (sourceMtimeMs > 0 && Date.now() - sourceMtimeMs <= CLI_NATIVE_HISTORY_FRESH_MS) return true;
17705
- return ptyNewest === 0 && nativeNewest > 0;
17706
- }
17707
18342
  function shouldPreserveReadChatPayloadField(key) {
17708
18343
  return key === "messageSource" || key === "transcriptProvenance";
17709
18344
  }
@@ -17768,6 +18403,8 @@ function normalizeReadChatCommandStatus(status, activeModal) {
17768
18403
  case "disconnected":
17769
18404
  case "not_monitored":
17770
18405
  return "error";
18406
+ case "waiting_approval":
18407
+ return hasNonEmptyModalButtons(activeModal) ? "waiting_approval" : "generating";
17771
18408
  default:
17772
18409
  return raw;
17773
18410
  }
@@ -17816,6 +18453,36 @@ function finalizeStreamingMessagesWhenIdle(messages, status) {
17816
18453
  };
17817
18454
  });
17818
18455
  }
18456
+ function collapseAdjacentDuplicateChatMessages(messages) {
18457
+ if (!Array.isArray(messages) || messages.length <= 1) return messages;
18458
+ const result = [];
18459
+ let prevRoleKind = "";
18460
+ let prevStripped = "";
18461
+ for (const message of messages) {
18462
+ const role = typeof message.role === "string" ? message.role : "";
18463
+ const kind = typeof message.kind === "string" ? message.kind : "standard";
18464
+ const content = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.map((p) => typeof p?.text === "string" ? p.text : "").join("") : "";
18465
+ const strippedContent = content.replace(/\s+/g, "");
18466
+ if (!strippedContent || role === "system") {
18467
+ result.push(message);
18468
+ prevRoleKind = "";
18469
+ prevStripped = "";
18470
+ continue;
18471
+ }
18472
+ const roleKind = `${role}:${kind}`;
18473
+ const sameStripped = strippedContent === prevStripped && roleKind === prevRoleKind;
18474
+ if (result.length > 0 && sameStripped) {
18475
+ result[result.length - 1] = message;
18476
+ prevRoleKind = roleKind;
18477
+ prevStripped = strippedContent;
18478
+ continue;
18479
+ }
18480
+ result.push(message);
18481
+ prevRoleKind = roleKind;
18482
+ prevStripped = strippedContent;
18483
+ }
18484
+ return result;
18485
+ }
17819
18486
  function buildReadChatCommandResult(payload, args) {
17820
18487
  let validatedPayload;
17821
18488
  const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
@@ -18338,7 +19005,9 @@ async function handleReadChat(h, args) {
18338
19005
  const activeModal = parsedRecord.activeModal ?? parsedRecord.modal ?? null;
18339
19006
  const returnedStatus = normalizeCliReadChatStatus(parsedRecord.status, activeModal, adapter, adapterStatus, parsedRecord.messages);
18340
19007
  const runtimeMessageMerger = getTargetInstance(h, args);
18341
- const parsedMessages = finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus);
19008
+ const parsedMessages = collapseAdjacentDuplicateChatMessages(
19009
+ finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus)
19010
+ );
18342
19011
  const returnedMessages = runtimeMessageMerger?.category === "cli" && runtimeMessageMerger.type === adapter.cliType && typeof runtimeMessageMerger.mergeRuntimeChatMessages === "function" ? runtimeMessageMerger.mergeRuntimeChatMessages(parsedMessages) : parsedMessages;
18343
19012
  const providerType = provider?.type || adapter.cliType;
18344
19013
  let selectedMessages = returnedMessages;
@@ -18349,30 +19018,22 @@ async function handleReadChat(h, args) {
18349
19018
  let selectedStatus = returnedStatus;
18350
19019
  const sessionWorkspace = typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : typeof adapter.workingDir === "string" ? adapter.workingDir : void 0;
18351
19020
  const intendedWorkspace = typeof args?.workspace === "string" ? args.workspace : void 0;
18352
- let messageSource = buildCliMessageSourceProvenance({
18353
- selected: "pty-parser",
18354
- provider: adapter.cliType,
18355
- fallbackReason: supportsCliNativeTranscript(providerType, provider) ? "native_history_not_checked" : "provider_native_transcript_not_supported",
18356
- sessionWorkspace,
18357
- intendedWorkspace,
18358
- ptyMessages: returnedMessages,
18359
- returnedMessages,
18360
- ptyStatusApprovalOnly: false
18361
- });
18362
- if (supportsCliNativeTranscript(providerType, provider) && isNativeSourceCanonicalHistory(provider?.canonicalHistory)) {
18363
- const agentStr = provider?.type || args?.agentType || getCurrentProviderType(h, adapter.cliType);
18364
- const workspace = sessionWorkspace;
18365
- const nativeHistoryLimit = Math.max(
18366
- normalizeReadChatTailLimit(args) || 0,
18367
- returnedMessages.length,
18368
- 200
18369
- );
18370
- const nativeHistorySessionId = resolveCliNativeHistorySessionId(args, historySessionId, providerSessionId);
18371
- const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
18372
- const exactNativeHistoryScope = Boolean(
18373
- 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()
18374
- );
18375
- let nativeHistory = null;
19021
+ const supportsNative = supportsCliNativeTranscript(providerType, provider) && isNativeSourceCanonicalHistory(provider?.canonicalHistory);
19022
+ const agentStr = provider?.type || args?.agentType || getCurrentProviderType(h, adapter.cliType);
19023
+ const workspace = sessionWorkspace;
19024
+ const nativeHistoryLimit = Math.max(
19025
+ normalizeReadChatTailLimit(args) || 0,
19026
+ returnedMessages.length,
19027
+ 200
19028
+ );
19029
+ const nativeHistorySessionId = supportsNative ? resolveCliNativeHistorySessionId(args, historySessionId, providerSessionId) : void 0;
19030
+ const targetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
19031
+ const exactNativeHistoryScope = Boolean(
19032
+ 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()
19033
+ );
19034
+ let nativeHistory = null;
19035
+ let nativeHistoryError;
19036
+ if (supportsNative) {
18376
19037
  try {
18377
19038
  nativeHistory = readCliProviderNativeHistory(agentStr, {
18378
19039
  canonicalHistory: provider?.canonicalHistory,
@@ -18386,210 +19047,148 @@ async function handleReadChat(h, args) {
18386
19047
  excludeInProgressTurn: returnedStatus === "waiting_approval"
18387
19048
  });
18388
19049
  } catch (error) {
18389
- const fallbackReason = `native_history_error:${error?.message || String(error)}`;
18390
- messageSource = buildCliMessageSourceProvenance({
18391
- selected: "pty-parser",
18392
- provider: adapter.cliType,
18393
- fallbackReason,
18394
- sessionWorkspace,
18395
- intendedWorkspace,
18396
- ptyMessages: returnedMessages,
18397
- returnedMessages,
18398
- ptyStatusApprovalOnly: false
18399
- });
19050
+ nativeHistoryError = error;
18400
19051
  nativeHistory = null;
18401
19052
  }
18402
- if (nativeHistory) {
18403
- const nativeMessages = Array.isArray(nativeHistory.messages) ? normalizeNativeHistoryMessages(agentStr, nativeHistory.messages, nativeHistory?.providerSessionId) : [];
18404
- const historyProviderSessionId = typeof nativeHistory?.providerSessionId === "string" ? nativeHistory.providerSessionId : readHistorySessionIdFromMessages(nativeMessages) || nativeHistorySessionId || historySessionId;
18405
- const nativeHistoryCoverage = typeof nativeHistory?.nativeHistoryCoverage === "string" ? nativeHistory.nativeHistoryCoverage : void 0;
18406
- const partialReason = typeof nativeHistory?.partialReason === "string" ? nativeHistory.partialReason : void 0;
18407
- const unavailableReason = typeof nativeHistory?.unavailableReason === "string" ? nativeHistory.unavailableReason : void 0;
18408
- const lookup = nativeHistory.lookup === "workspace" ? "workspace" : "session";
18409
- const transcriptWorkspace = typeof nativeHistory?.workspace === "string" ? nativeHistory.workspace : nativeMessages.map((message) => typeof message?.workspace === "string" ? message.workspace.trim() : "").find(Boolean);
18410
- const nativeHistorySessionForMapping = adapter.cliType === "antigravity-cli" && historyProviderSessionId && nativeHistorySessionId && historyProviderSessionId !== nativeHistorySessionId ? void 0 : nativeHistorySessionId;
18411
- const safeMapping = hasSafeNativeHistoryMapping({
18412
- historySessionId: lookup === "workspace" ? void 0 : nativeHistorySessionForMapping,
18413
- providerSessionId: lookup === "workspace" ? void 0 : historyProviderSessionId || providerSessionId,
18414
- workspace,
18415
- nativeMessages,
19053
+ }
19054
+ const nativeMessages = nativeHistory && Array.isArray(nativeHistory.messages) ? normalizeNativeHistoryMessages(agentStr, nativeHistory.messages, nativeHistory.providerSessionId) : [];
19055
+ const historyProviderSessionId = typeof nativeHistory?.providerSessionId === "string" ? nativeHistory.providerSessionId : readHistorySessionIdFromMessages(nativeMessages) || nativeHistorySessionId || historySessionId;
19056
+ const lookup = nativeHistory?.lookup === "workspace" ? "workspace" : "session";
19057
+ const nativeHistorySessionForMapping = adapter.cliType === "antigravity-cli" && historyProviderSessionId && nativeHistorySessionId && historyProviderSessionId !== nativeHistorySessionId ? void 0 : nativeHistorySessionId;
19058
+ const safeMapping = supportsNative && nativeHistory ? hasSafeNativeHistoryMapping({
19059
+ historySessionId: lookup === "workspace" ? void 0 : nativeHistorySessionForMapping,
19060
+ providerSessionId: lookup === "workspace" ? void 0 : historyProviderSessionId || providerSessionId,
19061
+ workspace,
19062
+ nativeMessages,
19063
+ ptyMessages: returnedMessages,
19064
+ requireWorkspaceContentOverlap: lookup === "workspace" && !exactNativeHistoryScope
19065
+ }) : false;
19066
+ const machineSessionKey = String(
19067
+ args?.targetSessionId || providerSessionId || historySessionId || h.currentSession?.sessionId || ""
19068
+ );
19069
+ const primary = decideCliReadChatSource({
19070
+ providerType,
19071
+ provider,
19072
+ sessionId: machineSessionKey,
19073
+ nativeHistoryResult: nativeHistory,
19074
+ nativeHistoryError,
19075
+ safeMapping,
19076
+ sessionWorkspace,
19077
+ intendedWorkspace,
19078
+ ptyMessages: returnedMessages,
19079
+ // Start with PTY visible; decideCliReadChatSource flips this
19080
+ // to true when the machine actually selects native-history.
19081
+ ptyStatusApprovalOnly: false
19082
+ });
19083
+ let messageSource = primary.messageSource;
19084
+ if (primary.nativeSelected) {
19085
+ selectedMessages = finalizeStreamingMessagesWhenIdle(primary.nativeMessages, returnedStatus);
19086
+ selectedProviderSessionId = historyProviderSessionId || providerSessionId;
19087
+ selectedTranscriptAuthority = "provider";
19088
+ selectedCoverage = nativeHistory?.hasMore ? "tail" : "full";
19089
+ } else if (supportsNative) {
19090
+ const liveCurrentRuntimePtySafe = isCurrentRuntimePtySafelyAttributed({
19091
+ adapter,
19092
+ helpers: h,
19093
+ readChatArgs: args,
19094
+ sessionWorkspace,
19095
+ intendedWorkspace,
19096
+ ptyMessages: returnedMessages
19097
+ });
19098
+ const mayProbeLiveCodexWorkspaceNative = adapter.cliType === "codex-cli" && liveCurrentRuntimePtySafe && !(typeof args?.providerSessionId === "string" && args.providerSessionId.trim()) && !(providerSessionId && providerSessionId.trim()) && (!historyProviderSessionId || historyProviderSessionId === nativeHistorySessionId || historyProviderSessionId === historySessionId);
19099
+ const liveWorkspaceNativeHistory = mayProbeLiveCodexWorkspaceNative ? readLiveCodexWorkspaceNativeHistory(agentStr, {
19100
+ canonicalHistory: provider?.canonicalHistory,
19101
+ workspace,
19102
+ offset: 0,
19103
+ limit: nativeHistoryLimit,
19104
+ excludeRecentCount: 0,
19105
+ historyBehavior: provider?.historyBehavior,
19106
+ scripts: provider?.scripts
19107
+ }) : null;
19108
+ const liveWorkspaceNativeMessages = Array.isArray(liveWorkspaceNativeHistory?.messages) ? normalizeNativeHistoryMessages(agentStr, liveWorkspaceNativeHistory.messages, liveWorkspaceNativeHistory?.providerSessionId) : [];
19109
+ const liveWorkspaceNativeProviderSessionId = typeof liveWorkspaceNativeHistory?.providerSessionId === "string" ? liveWorkspaceNativeHistory.providerSessionId : readHistorySessionIdFromMessages(liveWorkspaceNativeMessages);
19110
+ const liveWorkspaceNativeSafeMapping = liveWorkspaceNativeMessages.length > 0 && hasSafeNativeHistoryMapping({
19111
+ workspace,
19112
+ nativeMessages: liveWorkspaceNativeMessages,
19113
+ ptyMessages: returnedMessages,
19114
+ requireWorkspaceContentOverlap: true
19115
+ });
19116
+ if (liveWorkspaceNativeHistory) {
19117
+ const liveDecision = decideCliReadChatSource({
19118
+ providerType,
19119
+ provider,
19120
+ // Distinct session key so a transient codex live-probe does not
19121
+ // clobber the primary session's lock. The machine treats this
19122
+ // as its own session; the primary session's state is untouched.
19123
+ sessionId: `${machineSessionKey}::live-workspace`,
19124
+ nativeHistoryResult: liveWorkspaceNativeHistory,
19125
+ safeMapping: liveWorkspaceNativeSafeMapping,
19126
+ sessionWorkspace,
19127
+ intendedWorkspace,
18416
19128
  ptyMessages: returnedMessages,
18417
- requireWorkspaceContentOverlap: lookup === "workspace" && !exactNativeHistoryScope
18418
- });
18419
- const freshEnough = isNativeHistoryFreshEnough({
18420
- sourceMtimeMs: nativeHistory.sourceMtimeMs,
18421
- nativeMessages,
18422
- ptyMessages: returnedMessages
19129
+ ptyStatusApprovalOnly: true
18423
19130
  });
18424
- const nativeUsableForChatMessages = nativeHistory.source === "provider-native" && nativeMessages.length > 0 && nativeHistoryCoverage !== "partial" && nativeHistoryCoverage !== "unavailable" && safeMapping;
18425
- const NATIVE_ANCHOR_TTL_MS = 30 * 6e4;
18426
- const nativeAnchoredAt = adapter.nativeHistoryAnchoredAt ?? 0;
18427
- const nativeIsAnchored = nativeAnchoredAt > 0 && Date.now() - nativeAnchoredAt < NATIVE_ANCHOR_TTL_MS;
18428
- const allowStaleNativeChatMessages = (adapter.cliType === "antigravity-cli" || nativeIsAnchored) && nativeUsableForChatMessages;
18429
- if (nativeUsableForChatMessages && (freshEnough || allowStaleNativeChatMessages)) {
18430
- adapter.nativeHistoryAnchoredAt = Date.now();
18431
- selectedMessages = finalizeStreamingMessagesWhenIdle(nativeMessages, returnedStatus);
18432
- selectedProviderSessionId = historyProviderSessionId || providerSessionId;
19131
+ if (liveDecision.nativeSelected) {
19132
+ selectedMessages = finalizeStreamingMessagesWhenIdle(liveDecision.nativeMessages, returnedStatus);
19133
+ selectedProviderSessionId = liveWorkspaceNativeProviderSessionId || providerSessionId;
18433
19134
  selectedTranscriptAuthority = "provider";
18434
- selectedCoverage = nativeHistory.hasMore ? "tail" : "full";
18435
- messageSource = buildCliMessageSourceProvenance({
18436
- selected: "native-history",
18437
- provider: adapter.cliType,
18438
- nativeHandle: selectedProviderSessionId || nativeHistorySessionId || historySessionId,
18439
- sessionWorkspace,
18440
- intendedWorkspace,
18441
- transcriptWorkspace,
18442
- nativeSource: nativeHistory.source,
18443
- sourcePath: nativeHistory.sourcePath,
18444
- sourceMtimeMs: nativeHistory.sourceMtimeMs,
18445
- nativeHistoryCoverage,
18446
- partialReason,
18447
- unavailableReason,
18448
- nativeMessages,
18449
- ptyMessages: returnedMessages,
18450
- returnedMessages: selectedMessages,
18451
- safeMapping,
18452
- freshEnough,
18453
- ptyStatusApprovalOnly: true
18454
- });
19135
+ selectedCoverage = liveWorkspaceNativeHistory.hasMore ? "tail" : "full";
19136
+ messageSource = liveDecision.messageSource;
19137
+ messageSource.selectedDaemonSource = "live-workspace-native-history";
19138
+ messageSource.runtimeMappingSafe = true;
18455
19139
  } else {
18456
- if (!nativeUsableForChatMessages && adapter.nativeHistoryAnchoredAt) {
18457
- adapter.nativeHistoryAnchoredAt = 0;
18458
- }
18459
- const liveCurrentRuntimePtySafe = isCurrentRuntimePtySafelyAttributed({
19140
+ applyUnsafeNativeDaemonFallback({
19141
+ providerType,
18460
19142
  adapter,
18461
19143
  helpers: h,
18462
19144
  readChatArgs: args,
18463
19145
  sessionWorkspace,
18464
19146
  intendedWorkspace,
18465
- ptyMessages: returnedMessages
18466
- });
18467
- const mayProbeLiveCodexWorkspaceNative = adapter.cliType === "codex-cli" && liveCurrentRuntimePtySafe && !(typeof args?.providerSessionId === "string" && args.providerSessionId.trim()) && !(providerSessionId && providerSessionId.trim()) && (!historyProviderSessionId || historyProviderSessionId === nativeHistorySessionId || historyProviderSessionId === historySessionId);
18468
- const liveWorkspaceNativeHistory = mayProbeLiveCodexWorkspaceNative ? readLiveCodexWorkspaceNativeHistory(agentStr, {
18469
- canonicalHistory: provider?.canonicalHistory,
18470
- workspace,
18471
- offset: 0,
18472
- limit: nativeHistoryLimit,
18473
- excludeRecentCount: 0,
18474
- historyBehavior: provider?.historyBehavior,
18475
- scripts: provider?.scripts
18476
- }) : null;
18477
- const liveWorkspaceNativeMessages = Array.isArray(liveWorkspaceNativeHistory?.messages) ? normalizeNativeHistoryMessages(agentStr, liveWorkspaceNativeHistory.messages, liveWorkspaceNativeHistory?.providerSessionId) : [];
18478
- const liveWorkspaceNativeProviderSessionId = typeof liveWorkspaceNativeHistory?.providerSessionId === "string" ? liveWorkspaceNativeHistory.providerSessionId : readHistorySessionIdFromMessages(liveWorkspaceNativeMessages);
18479
- const liveWorkspaceTranscriptWorkspace = typeof liveWorkspaceNativeHistory?.workspace === "string" ? liveWorkspaceNativeHistory.workspace : liveWorkspaceNativeMessages.map((message) => typeof message?.workspace === "string" ? message.workspace.trim() : "").find(Boolean);
18480
- const liveWorkspaceNativeSafeMapping = liveWorkspaceNativeMessages.length > 0 && hasSafeNativeHistoryMapping({
18481
- workspace,
18482
- nativeMessages: liveWorkspaceNativeMessages,
18483
19147
  ptyMessages: returnedMessages,
18484
- requireWorkspaceContentOverlap: true
18485
- });
18486
- const liveWorkspaceNativeFreshEnough = liveWorkspaceNativeMessages.length > 0 && isNativeHistoryFreshEnough({
18487
- sourceMtimeMs: liveWorkspaceNativeHistory?.sourceMtimeMs,
18488
- nativeMessages: liveWorkspaceNativeMessages,
18489
- ptyMessages: returnedMessages
19148
+ nativeHistoryLimit,
19149
+ provider,
19150
+ messageSourceRef: { set(value) {
19151
+ messageSource = value;
19152
+ }, get() {
19153
+ return messageSource;
19154
+ } },
19155
+ apply(selection) {
19156
+ selectedMessages = selection.messages;
19157
+ selectedTranscriptAuthority = selection.transcriptAuthority;
19158
+ selectedCoverage = selection.coverage ?? coverage;
19159
+ selectedStatus = selection.status ?? returnedStatus;
19160
+ },
19161
+ activeModal,
19162
+ returnedStatus,
19163
+ coverage
18490
19164
  });
18491
- const liveWorkspaceNativeUsable = liveWorkspaceNativeHistory?.source === "provider-native" && liveWorkspaceNativeMessages.length > 0 && liveWorkspaceNativeHistory?.nativeHistoryCoverage !== "partial" && liveWorkspaceNativeHistory?.nativeHistoryCoverage !== "unavailable" && liveWorkspaceNativeSafeMapping && liveWorkspaceNativeFreshEnough;
18492
- if (liveWorkspaceNativeUsable) {
18493
- selectedMessages = finalizeStreamingMessagesWhenIdle(liveWorkspaceNativeMessages, returnedStatus);
18494
- selectedProviderSessionId = liveWorkspaceNativeProviderSessionId || providerSessionId;
18495
- selectedTranscriptAuthority = "provider";
18496
- selectedCoverage = liveWorkspaceNativeHistory.hasMore ? "tail" : "full";
18497
- messageSource = buildCliMessageSourceProvenance({
18498
- selected: "native-history",
18499
- provider: adapter.cliType,
18500
- nativeHandle: selectedProviderSessionId || nativeHistorySessionId || historySessionId,
18501
- sessionWorkspace,
18502
- intendedWorkspace,
18503
- transcriptWorkspace: liveWorkspaceTranscriptWorkspace,
18504
- nativeSource: liveWorkspaceNativeHistory.source,
18505
- sourcePath: liveWorkspaceNativeHistory.sourcePath,
18506
- sourceMtimeMs: liveWorkspaceNativeHistory.sourceMtimeMs,
18507
- nativeHistoryCoverage: liveWorkspaceNativeHistory.nativeHistoryCoverage,
18508
- partialReason: liveWorkspaceNativeHistory.partialReason,
18509
- unavailableReason: liveWorkspaceNativeHistory.unavailableReason,
18510
- nativeMessages: liveWorkspaceNativeMessages,
18511
- ptyMessages: returnedMessages,
18512
- returnedMessages: selectedMessages,
18513
- safeMapping: true,
18514
- freshEnough: true,
18515
- ptyStatusApprovalOnly: true
18516
- });
18517
- messageSource.selectedDaemonSource = "live-workspace-native-history";
18518
- messageSource.runtimeMappingSafe = true;
18519
- } else {
18520
- const fallbackReason = buildNativeHistoryFallbackReason({
18521
- providerType,
18522
- provider,
18523
- nativeSource: nativeHistory.source,
18524
- nativeHistoryCoverage,
18525
- unavailableReason,
18526
- nativeMessageCount: nativeMessages.length,
18527
- safeMapping,
18528
- freshEnough
18529
- });
18530
- const unsafeNativeFallback = adapter.cliType === "codex-cli" && isUnsafeNativeTranscriptFallback(fallbackReason);
18531
- const safeCurrentRuntimePtyMessages = unsafeNativeFallback && isCurrentRuntimePtySafelyAttributed({
18532
- adapter,
18533
- helpers: h,
18534
- readChatArgs: args,
18535
- sessionWorkspace,
18536
- intendedWorkspace,
18537
- ptyMessages: returnedMessages
18538
- });
18539
- const safeRuntimeAckMessages = unsafeNativeFallback && !safeCurrentRuntimePtyMessages ? selectRuntimeInputAckMessages(returnedMessages) : [];
18540
- const exactRuntimeMirrorMessages = unsafeNativeFallback && !safeCurrentRuntimePtyMessages && safeRuntimeAckMessages.length === 0 ? readExactRuntimeMirrorMessages({
18541
- providerType,
18542
- targetSessionId: typeof args?.targetSessionId === "string" ? args.targetSessionId : void 0,
18543
- currentSessionId: typeof h.currentSession?.sessionId === "string" ? h.currentSession.sessionId : void 0,
18544
- tailLimit: nativeHistoryLimit,
18545
- historyBehavior: provider?.historyBehavior
18546
- }) : [];
18547
- const safeDaemonMessages = safeRuntimeAckMessages.length > 0 ? safeRuntimeAckMessages : exactRuntimeMirrorMessages;
18548
- if (unsafeNativeFallback) {
18549
- if (safeCurrentRuntimePtyMessages) {
18550
- selectedMessages = returnedMessages;
18551
- selectedTranscriptAuthority = "daemon";
18552
- selectedCoverage = coverage || "current-turn";
18553
- selectedStatus = returnedStatus;
18554
- } else {
18555
- selectedMessages = safeDaemonMessages;
18556
- selectedTranscriptAuthority = safeDaemonMessages.length > 0 ? "daemon" : void 0;
18557
- selectedCoverage = safeDaemonMessages.length > 0 ? "tail" : void 0;
18558
- selectedStatus = coerceUnsafeNativeFallbackStatus(returnedStatus, activeModal);
18559
- }
18560
- }
18561
- messageSource = buildCliMessageSourceProvenance({
18562
- selected: "pty-parser",
18563
- provider: adapter.cliType,
18564
- nativeHandle: historyProviderSessionId || nativeHistorySessionId || historySessionId,
18565
- sessionWorkspace,
18566
- intendedWorkspace,
18567
- transcriptWorkspace,
18568
- fallbackReason,
18569
- nativeSource: nativeHistory.source,
18570
- sourcePath: nativeHistory.sourcePath,
18571
- sourceMtimeMs: nativeHistory.sourceMtimeMs,
18572
- nativeHistoryCoverage,
18573
- partialReason,
18574
- unavailableReason,
18575
- nativeMessages,
18576
- ptyMessages: returnedMessages,
18577
- returnedMessages: unsafeNativeFallback && !safeCurrentRuntimePtyMessages ? safeDaemonMessages : returnedMessages,
18578
- safeMapping,
18579
- freshEnough,
18580
- ptyStatusApprovalOnly: unsafeNativeFallback && !safeCurrentRuntimePtyMessages
18581
- });
18582
- if (safeCurrentRuntimePtyMessages) {
18583
- messageSource.selectedDaemonSource = "current-runtime-pty";
18584
- messageSource.transcriptAuthority = "daemon";
18585
- messageSource.runtimeMappingSafe = true;
18586
- }
18587
- if (unsafeNativeFallback && exactRuntimeMirrorMessages.length > 0) {
18588
- messageSource.selectedDaemonSource = "exact-runtime-mirror";
18589
- messageSource.transcriptAuthority = "daemon";
18590
- }
18591
- }
18592
19165
  }
19166
+ } else {
19167
+ applyUnsafeNativeDaemonFallback({
19168
+ providerType,
19169
+ adapter,
19170
+ helpers: h,
19171
+ readChatArgs: args,
19172
+ sessionWorkspace,
19173
+ intendedWorkspace,
19174
+ ptyMessages: returnedMessages,
19175
+ nativeHistoryLimit,
19176
+ provider,
19177
+ messageSourceRef: { set(value) {
19178
+ messageSource = value;
19179
+ }, get() {
19180
+ return messageSource;
19181
+ } },
19182
+ apply(selection) {
19183
+ selectedMessages = selection.messages;
19184
+ selectedTranscriptAuthority = selection.transcriptAuthority;
19185
+ selectedCoverage = selection.coverage ?? coverage;
19186
+ selectedStatus = selection.status ?? returnedStatus;
19187
+ },
19188
+ activeModal,
19189
+ returnedStatus,
19190
+ coverage
19191
+ });
18593
19192
  }
18594
19193
  }
18595
19194
  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}`);
@@ -18622,10 +19221,8 @@ async function handleReadChat(h, args) {
18622
19221
  const agentStr = provider?.type || args?.agentType || getCurrentProviderType(h);
18623
19222
  const workspace = typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
18624
19223
  const intendedWorkspace = typeof args?.workspace === "string" ? args.workspace : void 0;
18625
- const exactNativeHistoryScope = Boolean(
18626
- 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()
18627
- );
18628
- const history = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.canonicalHistory) ? readCliProviderNativeHistory(agentStr, {
19224
+ const supportsNative = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.canonicalHistory);
19225
+ const history = supportsNative ? readCliProviderNativeHistory(agentStr, {
18629
19226
  canonicalHistory: provider?.canonicalHistory,
18630
19227
  historySessionId,
18631
19228
  workspace,
@@ -18644,65 +19241,44 @@ async function handleReadChat(h, args) {
18644
19241
  historyBehavior: provider?.historyBehavior,
18645
19242
  scripts: provider?.scripts
18646
19243
  });
18647
- const lookup = history.lookup === "workspace" ? "workspace" : "session";
19244
+ const lookup = history?.lookup === "workspace" ? "workspace" : "session";
18648
19245
  const historyMessages = Array.isArray(history?.messages) ? normalizeNativeHistoryMessages(agentStr, history.messages, history?.providerSessionId) : [];
18649
19246
  const historyProviderSessionId = typeof history?.providerSessionId === "string" ? history.providerSessionId : readHistorySessionIdFromMessages(historyMessages) || historySessionId;
18650
- const nativeHistoryCoverage = typeof history?.nativeHistoryCoverage === "string" ? history.nativeHistoryCoverage : void 0;
18651
- const partialReason = typeof history?.partialReason === "string" ? history.partialReason : void 0;
18652
- const unavailableReason = typeof history?.unavailableReason === "string" ? history.unavailableReason : void 0;
18653
- const transcriptWorkspace = typeof history?.workspace === "string" ? history.workspace : historyMessages.map((message) => typeof message?.workspace === "string" ? message.workspace.trim() : "").find(Boolean);
18654
- const safeMapping = supportsCliNativeTranscript(agentStr, provider) ? hasSafeNativeHistoryMapping({
19247
+ const safeMapping = supportsNative ? hasSafeNativeHistoryMapping({
18655
19248
  historySessionId: lookup === "workspace" ? void 0 : historySessionId,
18656
19249
  providerSessionId: lookup === "workspace" ? void 0 : historyProviderSessionId,
18657
19250
  workspace,
18658
19251
  nativeMessages: historyMessages
18659
19252
  }) : false;
18660
- const nativeSelected = supportsCliNativeTranscript(agentStr, provider) && history.source === "provider-native" && historyMessages.length > 0 && nativeHistoryCoverage !== "partial" && nativeHistoryCoverage !== "unavailable" && safeMapping;
18661
- const messageSource = buildCliMessageSourceProvenance({
18662
- selected: nativeSelected ? "native-history" : "pty-parser",
18663
- provider: agentStr,
18664
- nativeHandle: historyProviderSessionId || historySessionId,
19253
+ const machineSessionKey = String(
19254
+ args?.targetSessionId || historyProviderSessionId || historySessionId || h.currentSession?.sessionId || ""
19255
+ );
19256
+ const decision = decideCliReadChatSource({
19257
+ providerType: agentStr,
19258
+ provider,
19259
+ sessionId: machineSessionKey,
19260
+ nativeHistoryResult: history,
19261
+ safeMapping,
18665
19262
  sessionWorkspace: workspace,
18666
19263
  intendedWorkspace,
18667
- transcriptWorkspace,
18668
- fallbackReason: nativeSelected ? void 0 : buildNativeHistoryFallbackReason({
18669
- providerType: agentStr,
18670
- provider,
18671
- nativeSource: history.source,
18672
- nativeHistoryCoverage,
18673
- unavailableReason,
18674
- nativeMessageCount: historyMessages.length,
18675
- safeMapping,
18676
- freshEnough: true
18677
- }),
18678
- nativeSource: history.source,
18679
- sourcePath: history.sourcePath,
18680
- sourceMtimeMs: history.sourceMtimeMs,
18681
- nativeHistoryCoverage,
18682
- partialReason,
18683
- unavailableReason,
18684
- nativeMessages: historyMessages,
18685
- returnedMessages: historyMessages,
18686
- safeMapping,
18687
- freshEnough: true,
19264
+ ptyMessages: [],
18688
19265
  ptyStatusApprovalOnly: false
18689
19266
  });
18690
- const requiresNativeSource = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.canonicalHistory);
18691
- if (requiresNativeSource && !nativeSelected) {
19267
+ if (supportsNative && !decision.nativeSelected) {
18692
19268
  return {
18693
19269
  success: false,
18694
19270
  code: "native_history_not_safely_available",
18695
19271
  error: "Provider-native history was not safely available for the requested CLI session.",
18696
19272
  providerSessionId: historyProviderSessionId,
18697
- messageSource,
18698
- transcriptProvenance: messageSource
19273
+ messageSource: decision.messageSource,
19274
+ transcriptProvenance: decision.messageSource
18699
19275
  };
18700
19276
  }
18701
19277
  return buildReadChatCommandResult({
18702
19278
  messages: historyMessages,
18703
19279
  status: "idle",
18704
- messageSource,
18705
- transcriptProvenance: messageSource,
19280
+ messageSource: decision.messageSource,
19281
+ transcriptProvenance: decision.messageSource,
18706
19282
  ...typeof history?.title === "string" ? { title: history.title } : {},
18707
19283
  ...historyProviderSessionId ? { providerSessionId: historyProviderSessionId } : {},
18708
19284
  ...provider?.historyBehavior?.transcriptAuthority === "provider" || provider?.historyBehavior?.transcriptAuthority === "daemon" ? { transcriptAuthority: (provider?.historyBehavior).transcriptAuthority } : {},
@@ -24930,6 +25506,10 @@ function validateCanonicalHistory(raw, errors) {
24930
25506
  if (mode !== void 0 && !["native-source", "materialized-mirror", "disabled"].includes(String(mode))) {
24931
25507
  errors.push("canonicalHistory.mode must be one of: native-source, materialized-mirror, disabled");
24932
25508
  }
25509
+ const chatContractVersion = canonicalHistory.contractVersion;
25510
+ if (chatContractVersion !== void 0 && chatContractVersion !== "1.0" && chatContractVersion !== "2.0") {
25511
+ errors.push(`canonicalHistory.contractVersion must be '1.0' or '2.0' when provided (got ${JSON.stringify(chatContractVersion)})`);
25512
+ }
24933
25513
  const scripts = canonicalHistory.scripts;
24934
25514
  if (scripts === void 0) return;
24935
25515
  if (!scripts || typeof scripts !== "object" || Array.isArray(scripts)) {
@@ -26168,7 +26748,7 @@ var ProviderLoader = class _ProviderLoader {
26168
26748
  return args ? args.map((arg) => /\s/.test(arg) ? JSON.stringify(arg) : arg).join(" ") : "";
26169
26749
  }
26170
26750
  const schemaDef = this.getSettingsSchema(providerType)[key];
26171
- const defaultVal = schemaDef ? key === "autoApprove" && schemaDef.type === "boolean" ? true : schemaDef.default : void 0;
26751
+ const defaultVal = schemaDef ? schemaDef.default : void 0;
26172
26752
  const config = this.readConfig();
26173
26753
  const userVal = config?.providerSettings?.[providerType]?.[key];
26174
26754
  return userVal !== void 0 ? userVal : defaultVal;
@@ -26270,7 +26850,6 @@ var ProviderLoader = class _ProviderLoader {
26270
26850
  if (result.autoApprove?.type === "boolean") {
26271
26851
  result.autoApprove = {
26272
26852
  ...result.autoApprove,
26273
- default: true,
26274
26853
  public: true,
26275
26854
  label: result.autoApprove.label || "Auto Approve",
26276
26855
  description: result.autoApprove.description || "Automatically approve actionable prompts without sending approval alerts."
@@ -26292,7 +26871,10 @@ var ProviderLoader = class _ProviderLoader {
26292
26871
  if (!provider.settings?.autoApprove) {
26293
26872
  result.autoApprove = {
26294
26873
  type: "boolean",
26295
- default: true,
26874
+ // (fix) Safe default is *off*. Auto-approving every modal without the
26875
+ // user opting in produced silent-bash-execution surprises and the
26876
+ // "Auto-approved: ..." system-message flood seen on AGY/Codex.
26877
+ default: false,
26296
26878
  public: true,
26297
26879
  label: "Auto Approve",
26298
26880
  description: "Automatically approve actionable prompts without sending approval alerts."
@@ -27589,15 +28171,22 @@ function getSessionMessageUpdatedAt(session) {
27589
28171
  return getMessageEventTime(lastMessage);
27590
28172
  }
27591
28173
  function getSessionCompletionMarker(session) {
27592
- const lastMessage = session.activeChat?.messages?.at?.(-1);
27593
- if (!lastMessage) return "";
27594
- const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
27595
- if (role === "user" || role === "human" || role === "system") return "";
27596
- if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
27597
- if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
27598
- if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
27599
- const timestamp = getMessageEventTime(lastMessage);
27600
- return timestamp > 0 ? `ts:${timestamp}` : "";
28174
+ const messages = session.activeChat?.messages;
28175
+ if (!Array.isArray(messages) || messages.length === 0) return "";
28176
+ for (let i = messages.length - 1; i >= 0; i -= 1) {
28177
+ const m = messages[i];
28178
+ const role = typeof m?.role === "string" ? m.role : "";
28179
+ const kind = typeof m?.kind === "string" ? m.kind : "";
28180
+ if (role === "user" || role === "human") return "";
28181
+ if (role === "system") continue;
28182
+ if (kind === "tool") continue;
28183
+ if (typeof m._turnKey === "string" && m._turnKey) return `turn:${m._turnKey}`;
28184
+ if (typeof m.id === "string" && m.id) return `id:${m.id}`;
28185
+ if (typeof m.index === "number" && Number.isFinite(m.index)) return `idx:${m.index}`;
28186
+ const timestamp = getMessageEventTime(m);
28187
+ return timestamp > 0 ? `ts:${timestamp}` : "";
28188
+ }
28189
+ return "";
27601
28190
  }
27602
28191
  function getSessionLastUsedAt(session) {
27603
28192
  return getSessionMessageUpdatedAt(session) || session.lastUpdated || Date.now();
@@ -27612,7 +28201,8 @@ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRo
27612
28201
  if (status === "generating" || status === "starting") {
27613
28202
  return { unread: false, inboxBucket: "working" };
27614
28203
  }
27615
- const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human" && lastRole !== "system";
28204
+ const ignorableTrailingRoles = lastRole === "user" || lastRole === "human" || lastRole === "system" || lastRole === "tool";
28205
+ const unread = completionMarker ? seenCompletionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && !ignorableTrailingRoles : hasContentChange && lastUsedAt > lastSeenAt && !ignorableTrailingRoles;
27616
28206
  return { unread, inboxBucket: unread ? "task_complete" : "idle" };
27617
28207
  }
27618
28208
  function projectLiveSessionFromFull(session) {
@@ -30976,7 +31566,8 @@ var DaemonCommandRouter = class {
30976
31566
  }
30977
31567
  case "get_pending_mesh_events": {
30978
31568
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
30979
- const events = drainPendingMeshCoordinatorEvents(meshId || void 0);
31569
+ const coordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
31570
+ const events = drainPendingMeshCoordinatorEvents(meshId || void 0, coordinatorDaemonId);
30980
31571
  return { success: true, events };
30981
31572
  }
30982
31573
  case "launch_cli":
@@ -32952,7 +33543,8 @@ ${block2}`);
32952
33543
  finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
32953
33544
  nodeStatuses.push(status);
32954
33545
  }
32955
- const pendingCoordinatorEvents = drainPendingMeshCoordinatorEvents(meshId);
33546
+ const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
33547
+ const pendingCoordinatorEvents = drainPendingMeshCoordinatorEvents(meshId, callerCoordinatorDaemonId);
32956
33548
  const previewFreshness = (() => {
32957
33549
  const localRepoRoot = nodeStatuses.map((node) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace)).find((candidate) => !!candidate && fs11.existsSync(candidate));
32958
33550
  return localRepoRoot ? buildPreviewFreshness(localRepoRoot) : void 0;
@@ -33430,6 +34022,7 @@ function prepareSessionChatTailUpdate(input) {
33430
34022
  const title = typeof result.title === "string" ? result.title : void 0;
33431
34023
  const activeModal = normalizeChatTailActiveModal(result.activeModal);
33432
34024
  const status = typeof result.status === "string" ? result.status : "idle";
34025
+ const messageSource = result.messageSource && typeof result.messageSource === "object" ? result.messageSource : void 0;
33433
34026
  const deliverySignature = buildChatTailDeliverySignature({
33434
34027
  sessionId: input.sessionId,
33435
34028
  ...input.historySessionId ? { historySessionId: input.historySessionId } : {},
@@ -33462,7 +34055,8 @@ function prepareSessionChatTailUpdate(input) {
33462
34055
  messages,
33463
34056
  status,
33464
34057
  ...title ? { title } : {},
33465
- ...activeModal ? { activeModal } : {}
34058
+ ...activeModal ? { activeModal } : {},
34059
+ ...messageSource ? { messageSource } : {}
33466
34060
  }
33467
34061
  };
33468
34062
  }