adhdev 0.9.63 → 0.9.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8642,10 +8642,6 @@ function buildChatTailDeliverySignature(payload) {
8642
8642
  payload.historySessionId || "",
8643
8643
  payload.status,
8644
8644
  payload.title || "",
8645
- payload.syncMode,
8646
- String(payload.replaceFrom),
8647
- String(payload.totalMessages),
8648
- payload.lastMessageSignature,
8649
8645
  payload.activeModal ? `${payload.activeModal.message}|${payload.activeModal.buttons.join("")}` : "",
8650
8646
  stringifySignatureMessages(payload.messages)
8651
8647
  ]);
@@ -8763,99 +8759,13 @@ function parseMaybeJson(value) {
8763
8759
  return value;
8764
8760
  }
8765
8761
  }
8766
- function getChatMessageSignature(message) {
8767
- return buildChatMessageSignature(message);
8768
- }
8769
- function normalizeReadChatCursor(args) {
8770
- const knownMessageCount = Math.max(0, Number(args?.knownMessageCount || 0));
8771
- const lastMessageSignature = typeof args?.lastMessageSignature === "string" ? args.lastMessageSignature : "";
8772
- const tailLimit = Math.max(0, Number(args?.tailLimit || 0));
8773
- return { knownMessageCount, lastMessageSignature, tailLimit };
8762
+ function normalizeReadChatTailLimit(args) {
8763
+ const value = Number(args?.tailLimit || 0);
8764
+ return Number.isFinite(value) ? Math.max(0, value) : 0;
8774
8765
  }
8775
8766
  function normalizeReadChatMessages(payload) {
8776
8767
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
8777
- return normalizeChatMessages(messages);
8778
- }
8779
- function normalizeReadChatReplayTextContent(content) {
8780
- return flattenContent(content || "").replace(/\s+/g, " ").trim();
8781
- }
8782
- function getReadChatReplayCollapseInfo(message) {
8783
- if (!message) return null;
8784
- const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
8785
- const kind = typeof message.kind === "string" ? message.kind.trim().toLowerCase() : "standard";
8786
- const senderName = typeof message.senderName === "string" ? message.senderName.trim().toLowerCase() : "";
8787
- const collapsible = role === "assistant" || role === "system";
8788
- if (!collapsible) return { role, kind, senderName, content: "", signature: "", collapsible };
8789
- const content = normalizeReadChatReplayTextContent(message.content);
8790
- return {
8791
- role,
8792
- kind,
8793
- senderName,
8794
- content,
8795
- signature: `${role}:${kind}:${senderName}:${content}`,
8796
- collapsible
8797
- };
8798
- }
8799
- function isStableReadChatAssistantAnswerInfo(info) {
8800
- if (!info) return false;
8801
- if (info.role !== "assistant") return false;
8802
- if (info.kind && info.kind !== "standard") return false;
8803
- if (info.content.length < 160) return false;
8804
- if (/^(bash|shell|terminal) command\b/i.test(info.content)) return false;
8805
- return true;
8806
- }
8807
- function isReplayedAssistantAnswerAfterStableAnswerInfo(info, stableContent) {
8808
- if (!info || !stableContent) return false;
8809
- if (info.role !== "assistant") return false;
8810
- if (info.kind && info.kind !== "standard") return false;
8811
- const content = info.content;
8812
- if (content.length < 80 || stableContent.length < 80) return false;
8813
- return content === stableContent || content.startsWith(stableContent) || stableContent.startsWith(content);
8814
- }
8815
- function collapseReplayDuplicatesFromReadChat(messages) {
8816
- const collapsed = [];
8817
- const replaySignaturesInCurrentTurn = /* @__PURE__ */ new Set();
8818
- let stableAssistantAnswerContentInCurrentTurn = "";
8819
- let stableAssistantAnswerCollapsedIndex = -1;
8820
- let stableAssistantAnswerHadInterveningActivity = false;
8821
- let previousReplaySignature = "";
8822
- for (const message of messages) {
8823
- const info = getReadChatReplayCollapseInfo(message);
8824
- if (info?.role === "user") {
8825
- replaySignaturesInCurrentTurn.clear();
8826
- stableAssistantAnswerContentInCurrentTurn = "";
8827
- stableAssistantAnswerCollapsedIndex = -1;
8828
- stableAssistantAnswerHadInterveningActivity = false;
8829
- previousReplaySignature = "";
8830
- }
8831
- if (info?.collapsible && info.signature) {
8832
- if (previousReplaySignature === info.signature) continue;
8833
- if (replaySignaturesInCurrentTurn.has(info.signature)) continue;
8834
- if (isReplayedAssistantAnswerAfterStableAnswerInfo(info, stableAssistantAnswerContentInCurrentTurn)) {
8835
- const isAdjacentFullerAssistantAnswer = info.role === "assistant" && (!info.kind || info.kind === "standard") && stableAssistantAnswerCollapsedIndex >= 0 && stableAssistantAnswerCollapsedIndex === collapsed.length - 1 && !stableAssistantAnswerHadInterveningActivity && info.content.length > stableAssistantAnswerContentInCurrentTurn.length && info.content.startsWith(stableAssistantAnswerContentInCurrentTurn);
8836
- if (isAdjacentFullerAssistantAnswer) {
8837
- collapsed[stableAssistantAnswerCollapsedIndex] = message;
8838
- replaySignaturesInCurrentTurn.add(info.signature);
8839
- stableAssistantAnswerContentInCurrentTurn = info.content;
8840
- previousReplaySignature = info.signature;
8841
- }
8842
- continue;
8843
- }
8844
- }
8845
- collapsed.push(message);
8846
- previousReplaySignature = info?.collapsible ? info.signature : "";
8847
- if (info?.collapsible && info.signature) {
8848
- replaySignaturesInCurrentTurn.add(info.signature);
8849
- }
8850
- if (isStableReadChatAssistantAnswerInfo(info)) {
8851
- stableAssistantAnswerContentInCurrentTurn = info?.content || "";
8852
- stableAssistantAnswerCollapsedIndex = collapsed.length - 1;
8853
- stableAssistantAnswerHadInterveningActivity = false;
8854
- } else if (stableAssistantAnswerContentInCurrentTurn && info?.role === "assistant" && (!info.kind || info.kind !== "standard")) {
8855
- stableAssistantAnswerHadInterveningActivity = true;
8856
- }
8857
- }
8858
- return collapsed;
8768
+ return messages;
8859
8769
  }
8860
8770
  function deriveHistoryDedupKey(message) {
8861
8771
  const unitKey = typeof message._unitKey === "string" ? message._unitKey.trim() : "";
@@ -8880,102 +8790,12 @@ function toHistoryPersistedMessages(messages) {
8880
8790
  historyDedupKey: deriveHistoryDedupKey(message)
8881
8791
  }));
8882
8792
  }
8883
- function findLastMessageIndexBySignature(messages, signature) {
8884
- if (!signature) return -1;
8885
- for (let index = messages.length - 1; index >= 0; index -= 1) {
8886
- if (getChatMessageSignature(messages[index]) === signature) {
8887
- return index;
8888
- }
8889
- }
8890
- return -1;
8891
- }
8892
- function buildBoundedTailSync(messages, cursor) {
8793
+ function buildFullTail(messages, tailLimit) {
8893
8794
  const totalMessages = messages.length;
8894
- const tailMessages = cursor.tailLimit > 0 && totalMessages > cursor.tailLimit ? messages.slice(-cursor.tailLimit) : messages;
8795
+ const tailMessages = tailLimit > 0 ? messages.slice(-tailLimit) : messages;
8895
8796
  return {
8896
- syncMode: "full",
8897
- replaceFrom: 0,
8898
8797
  messages: tailMessages,
8899
- totalMessages,
8900
- lastMessageSignature: getChatMessageSignature(messages[totalMessages - 1])
8901
- };
8902
- }
8903
- function computeReadChatSync(messages, cursor) {
8904
- const totalMessages = messages.length;
8905
- const lastMessageSignature = getChatMessageSignature(messages[totalMessages - 1]);
8906
- const { knownMessageCount, lastMessageSignature: knownSignature } = cursor;
8907
- if (!knownMessageCount || !knownSignature) {
8908
- return {
8909
- syncMode: "full",
8910
- replaceFrom: 0,
8911
- messages,
8912
- totalMessages,
8913
- lastMessageSignature
8914
- };
8915
- }
8916
- if (knownMessageCount > totalMessages) {
8917
- return {
8918
- syncMode: "full",
8919
- replaceFrom: 0,
8920
- messages,
8921
- totalMessages,
8922
- lastMessageSignature
8923
- };
8924
- }
8925
- if (knownMessageCount === totalMessages && knownSignature === lastMessageSignature) {
8926
- return {
8927
- syncMode: "noop",
8928
- replaceFrom: totalMessages,
8929
- messages: [],
8930
- totalMessages,
8931
- lastMessageSignature
8932
- };
8933
- }
8934
- if (cursor.tailLimit > 0 && knownSignature === lastMessageSignature) {
8935
- const requestedTailCount = Math.min(totalMessages, cursor.tailLimit);
8936
- if (knownMessageCount >= requestedTailCount) {
8937
- return {
8938
- syncMode: "noop",
8939
- replaceFrom: totalMessages,
8940
- messages: [],
8941
- totalMessages,
8942
- lastMessageSignature
8943
- };
8944
- }
8945
- return buildBoundedTailSync(messages, cursor);
8946
- }
8947
- if (knownMessageCount < totalMessages) {
8948
- const anchorSignature = getChatMessageSignature(messages[knownMessageCount - 1]);
8949
- if (anchorSignature === knownSignature) {
8950
- return {
8951
- syncMode: "append",
8952
- replaceFrom: knownMessageCount,
8953
- messages: messages.slice(knownMessageCount),
8954
- totalMessages,
8955
- lastMessageSignature
8956
- };
8957
- }
8958
- if (cursor.tailLimit > 0) {
8959
- const signatureIndex = findLastMessageIndexBySignature(messages, knownSignature);
8960
- if (signatureIndex >= 0) {
8961
- return {
8962
- syncMode: "append",
8963
- replaceFrom: knownMessageCount,
8964
- messages: messages.slice(signatureIndex + 1),
8965
- totalMessages,
8966
- lastMessageSignature
8967
- };
8968
- }
8969
- return buildBoundedTailSync(messages, cursor);
8970
- }
8971
- }
8972
- const replaceFrom = Math.max(0, Math.min(knownMessageCount - 1, totalMessages));
8973
- return {
8974
- syncMode: replaceFrom === 0 ? "full" : "replace_tail",
8975
- replaceFrom,
8976
- messages: replaceFrom === 0 ? messages : messages.slice(replaceFrom),
8977
- totalMessages,
8978
- lastMessageSignature
8798
+ totalMessages
8979
8799
  };
8980
8800
  }
8981
8801
  function hasNonEmptyModalButtons(activeModal) {
@@ -9010,31 +8830,13 @@ function buildReadChatCommandResult(payload, args) {
9010
8830
  } catch (error48) {
9011
8831
  return { success: false, error: error48?.message || String(error48) };
9012
8832
  }
9013
- const messages = collapseReplayDuplicatesFromReadChat(normalizeReadChatMessages(validatedPayload));
9014
- const cursor = normalizeReadChatCursor(args);
9015
- if (!cursor.knownMessageCount && !cursor.lastMessageSignature && cursor.tailLimit > 0 && messages.length > cursor.tailLimit) {
9016
- const tailMessages = messages.slice(-cursor.tailLimit);
9017
- const lastMessageSignature = getChatMessageSignature(tailMessages[tailMessages.length - 1]);
9018
- return {
9019
- success: true,
9020
- ...validatedPayload,
9021
- messages: tailMessages,
9022
- syncMode: "full",
9023
- replaceFrom: 0,
9024
- totalMessages: messages.length,
9025
- lastMessageSignature,
9026
- ...debugReadChat ? { debugReadChat } : {}
9027
- };
9028
- }
9029
- const sync = computeReadChatSync(messages, cursor);
8833
+ const messages = normalizeReadChatMessages(validatedPayload);
8834
+ const sync = buildFullTail(messages, normalizeReadChatTailLimit(args));
9030
8835
  return {
9031
8836
  success: true,
9032
8837
  ...validatedPayload,
9033
8838
  messages: sync.messages,
9034
- syncMode: sync.syncMode,
9035
- replaceFrom: sync.replaceFrom,
9036
8839
  totalMessages: sync.totalMessages,
9037
- lastMessageSignature: sync.lastMessageSignature,
9038
8840
  ...debugReadChat ? { debugReadChat } : {}
9039
8841
  };
9040
8842
  }
@@ -9252,10 +9054,6 @@ async function handleGetChatDebugBundle(h, args) {
9252
9054
  status: readResult.status,
9253
9055
  title: readResult.title,
9254
9056
  totalMessages: readResult.totalMessages,
9255
- returnedMessages: Array.isArray(readResult.messages) ? readResult.messages.length : void 0,
9256
- syncMode: readResult.syncMode,
9257
- replaceFrom: readResult.replaceFrom,
9258
- lastMessageSignature: readResult.lastMessageSignature,
9259
9057
  providerSessionId: readResult.providerSessionId,
9260
9058
  transcriptAuthority: readResult.transcriptAuthority,
9261
9059
  coverage: readResult.coverage,
@@ -9365,22 +9163,13 @@ function toNonNegativeNumber(value) {
9365
9163
  return Number.isFinite(numeric) ? Math.max(0, numeric) : 0;
9366
9164
  }
9367
9165
  function getCliVisibleTranscriptCount(adapter) {
9368
- const adapterStatus = adapter?.getStatus?.() || {};
9369
- const adapterMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
9370
- let parsedRecord = null;
9371
- if (typeof adapter?.getScriptParsedStatus === "function") {
9372
- try {
9373
- const parsed = parseMaybeJson(adapter.getScriptParsedStatus());
9374
- parsedRecord = parsed && typeof parsed === "object" ? parsed : null;
9375
- } catch {
9376
- parsedRecord = null;
9377
- }
9166
+ if (typeof adapter?.getScriptParsedStatus !== "function") return 0;
9167
+ try {
9168
+ const parsed = parseMaybeJson(adapter.getScriptParsedStatus());
9169
+ return Array.isArray(parsed?.messages) ? parsed.messages.length : 0;
9170
+ } catch {
9171
+ return 0;
9378
9172
  }
9379
- const parsedMessages = Array.isArray(parsedRecord?.messages) ? parsedRecord.messages : [];
9380
- if (!parsedRecord) return adapterMessages.length;
9381
- const parsedIsProviderAuthoritative = parsedRecord.transcriptAuthority === "provider" || parsedRecord.coverage === "full";
9382
- const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && adapterMessages.length > 0 && adapterMessages.length > parsedMessages.length;
9383
- return shouldPreferAdapterMessages ? adapterMessages.length : parsedMessages.length;
9384
9173
  }
9385
9174
  async function getStableExtensionBaseline(h) {
9386
9175
  const first = await readExtensionChatState(h);
@@ -9442,52 +9231,46 @@ async function handleReadChat(h, args) {
9442
9231
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
9443
9232
  if (adapter) {
9444
9233
  _log(`${transport} adapter: ${adapter.cliType}`);
9234
+ if (typeof adapter.getScriptParsedStatus !== "function") {
9235
+ return { success: false, error: `${transport} adapter parseSession unavailable` };
9236
+ }
9445
9237
  let parsedStatus = null;
9446
- if (typeof adapter.getScriptParsedStatus === "function") {
9447
- try {
9448
- parsedStatus = parseMaybeJson(adapter.getScriptParsedStatus());
9449
- } catch (error48) {
9450
- return { success: false, error: error48?.message || String(error48) };
9451
- }
9238
+ try {
9239
+ parsedStatus = parseMaybeJson(adapter.getScriptParsedStatus());
9240
+ } catch (error48) {
9241
+ return { success: false, error: error48?.message || String(error48) };
9452
9242
  }
9453
9243
  const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
9454
- const adapterStatus = adapter.getStatus();
9455
- const parsedIsProviderAuthoritative = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.coverage === "full";
9456
- const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
9457
- const parsedShowsApproval = hasNonEmptyModalButtons(parsedRecord?.activeModal) && parsedRecord?.status === "waiting_approval";
9458
- const status = parsedRecord ? {
9459
- ...parsedRecord,
9460
- messages: shouldPreferAdapterMessages ? adapterStatus.messages : parsedRecord.messages,
9461
- status: parsedShowsApproval ? parsedRecord.status : adapterStatus.status !== "idle" ? adapterStatus.status : parsedRecord.status || adapterStatus.status,
9462
- activeModal: parsedRecord.activeModal || adapterStatus.activeModal
9463
- } : adapterStatus;
9464
- const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
9465
- const providerSessionId = typeof parsedRecord?.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
9466
- const transcriptAuthority = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
9467
- const coverage = parsedRecord?.coverage === "full" || parsedRecord?.coverage === "tail" || parsedRecord?.coverage === "current-turn" ? parsedRecord.coverage : void 0;
9468
- if (status) {
9469
- LOG.debug("Command", `[read_chat] cli-like resolved provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord?.status || "")} shouldPreferAdapterMessages=${String(shouldPreferAdapterMessages)} adapterMsgCount=${Array.isArray(adapterStatus.messages) ? adapterStatus.messages.length : 0} parsedMsgCount=${Array.isArray(parsedRecord?.messages) ? parsedRecord.messages.length : 0} returnedMsgCount=${Array.isArray(status.messages) ? status.messages.length : 0}`);
9470
- return buildReadChatCommandResult({
9471
- messages: status.messages || [],
9472
- status: status.status,
9473
- activeModal: status.activeModal,
9474
- debugReadChat: {
9475
- provider: adapter.cliType,
9476
- targetSessionId: String(args?.targetSessionId || ""),
9477
- adapterStatus: String(adapterStatus.status || ""),
9478
- parsedStatus: String(parsedRecord?.status || ""),
9479
- returnedStatus: String(status.status || ""),
9480
- shouldPreferAdapterMessages,
9481
- adapterMsgCount: Array.isArray(adapterStatus.messages) ? adapterStatus.messages.length : 0,
9482
- parsedMsgCount: Array.isArray(parsedRecord?.messages) ? parsedRecord.messages.length : 0,
9483
- returnedMsgCount: Array.isArray(status.messages) ? status.messages.length : 0
9484
- },
9485
- ...title ? { title } : {},
9486
- ...providerSessionId ? { providerSessionId } : {},
9487
- ...transcriptAuthority ? { transcriptAuthority } : {},
9488
- ...coverage ? { coverage } : {}
9489
- }, args);
9490
- }
9244
+ if (!parsedRecord || !Array.isArray(parsedRecord.messages)) {
9245
+ return { success: false, error: `${transport} parser did not return messages` };
9246
+ }
9247
+ const adapterStatus = typeof adapter.getStatus === "function" ? adapter.getStatus() : {};
9248
+ const title = typeof parsedRecord.title === "string" ? parsedRecord.title : void 0;
9249
+ const providerSessionId = typeof parsedRecord.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
9250
+ const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
9251
+ const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
9252
+ const activeModal = parsedRecord.activeModal ?? parsedRecord.modal ?? null;
9253
+ const returnedStatus = parsedRecord.status || "idle";
9254
+ 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}`);
9255
+ return buildReadChatCommandResult({
9256
+ messages: parsedRecord.messages,
9257
+ status: returnedStatus,
9258
+ activeModal,
9259
+ debugReadChat: {
9260
+ provider: adapter.cliType,
9261
+ targetSessionId: String(args?.targetSessionId || ""),
9262
+ adapterStatus: String(adapterStatus.status || ""),
9263
+ parsedStatus: String(parsedRecord.status || ""),
9264
+ returnedStatus: String(returnedStatus || ""),
9265
+ shouldPreferAdapterMessages: false,
9266
+ parsedMsgCount: parsedRecord.messages.length,
9267
+ returnedMsgCount: parsedRecord.messages.length
9268
+ },
9269
+ ...title ? { title } : {},
9270
+ ...providerSessionId ? { providerSessionId } : {},
9271
+ ...transcriptAuthority ? { transcriptAuthority } : {},
9272
+ ...coverage ? { coverage } : {}
9273
+ }, args);
9491
9274
  }
9492
9275
  return { success: false, error: `${transport} adapter not found` };
9493
9276
  }
@@ -10341,7 +10124,6 @@ var init_chat_commands = __esm({
10341
10124
  init_logger();
10342
10125
  init_debug_trace();
10343
10126
  init_chat_signatures();
10344
- init_chat_message_normalization();
10345
10127
  RECENT_SEND_WINDOW_MS = 1200;
10346
10128
  READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25e3;
10347
10129
  recentSendByTarget = /* @__PURE__ */ new Map();
@@ -13081,67 +12863,6 @@ function promptLikelyVisible(screenText, promptSnippet) {
13081
12863
  function normalizeScreenSnapshot(text) {
13082
12864
  return sanitizeTerminalText(String(text || "")).replace(/\s+/g, " ").trim();
13083
12865
  }
13084
- function shouldReflowComparableMessageLines(lines) {
13085
- return Array.isArray(lines) && lines.length > 1 && lines.slice(0, -1).every((line) => String(line || "").trim().length >= 48) && !lines.some((line) => /^```/.test(line)) && !lines.some((line) => /^\|/.test(line)) && !lines.some((line) => /^\s*(?:[-*+] |\d+\.\s)/.test(line));
13086
- }
13087
- function joinComparableMessageLines(lines) {
13088
- return lines.reduce((acc, line) => {
13089
- const next = String(line || "").trim();
13090
- if (!next) return acc;
13091
- if (!acc) return next;
13092
- if (/[,\d]$/.test(acc) && /^\d/.test(next)) {
13093
- return `${acc}${next}`;
13094
- }
13095
- if (/[A-Za-z]$/.test(acc) && /^\d/.test(next)) {
13096
- return `${acc}${next}`;
13097
- }
13098
- const fragmentMatch = acc.match(/([A-Za-z]{1,4})$/);
13099
- const fragment = fragmentMatch ? fragmentMatch[1].toLowerCase() : "";
13100
- if (/^[a-z]/.test(next) && fragment && !COMMON_COMPARABLE_WRAP_WORDS.has(fragment)) {
13101
- return `${acc}${next}`;
13102
- }
13103
- return `${acc} ${next}`;
13104
- }, "").replace(/\s+([,.;:!?])/g, "$1").replace(/(\d)\s+,/g, "$1,").replace(/\s+/g, " ").trim();
13105
- }
13106
- function normalizeComparableMessageContent(text) {
13107
- const lines = String(text || "").split(/\r\n|\n|\r/g).map((line) => line.trim()).filter(Boolean);
13108
- if (lines.length === 0) return "";
13109
- if (shouldReflowComparableMessageLines(lines)) {
13110
- return joinComparableMessageLines(lines);
13111
- }
13112
- return lines.join(" ").replace(/\s+/g, " ").trim();
13113
- }
13114
- function trimPromptEchoPrefix(text, promptText) {
13115
- const prompt2 = normalizeComparableMessageContent(String(promptText || ""));
13116
- if (!prompt2) return String(text || "");
13117
- const lines = String(text || "").split(/\r\n|\n|\r/g);
13118
- let dropCount = 0;
13119
- for (let index = 0; index < Math.min(lines.length, 6); index += 1) {
13120
- const fragment = normalizeComparableMessageContent(lines[index].replace(/^[.…]+\s*/, ""));
13121
- if (!fragment) {
13122
- if (dropCount === index) dropCount = index + 1;
13123
- continue;
13124
- }
13125
- const fragmentWordCount = fragment ? fragment.split(/\s+/).filter(Boolean).length : 0;
13126
- const canBePromptEcho = fragment.length >= 16 || fragmentWordCount >= 4;
13127
- if (canBePromptEcho && prompt2.includes(fragment)) {
13128
- dropCount = index + 1;
13129
- continue;
13130
- }
13131
- break;
13132
- }
13133
- return lines.slice(dropCount).join("\n").trim();
13134
- }
13135
- function getLastUserPromptText(messages) {
13136
- const items = Array.isArray(messages) ? messages : [];
13137
- for (let index = items.length - 1; index >= 0; index -= 1) {
13138
- const message = items[index];
13139
- if (message?.role === "user" && typeof message.content === "string" && message.content.trim()) {
13140
- return message.content;
13141
- }
13142
- }
13143
- return "";
13144
- }
13145
12866
  function parsePatternEntry(x) {
13146
12867
  if (x instanceof RegExp) return x;
13147
12868
  if (x && typeof x === "object" && typeof x.source === "string") {
@@ -13168,7 +12889,7 @@ function normalizeCliProviderForRuntime(raw) {
13168
12889
  }
13169
12890
  };
13170
12891
  }
13171
- var os11, path13, import_child_process4, buildCliSpawnEnv, COMMON_COMPARABLE_WRAP_WORDS;
12892
+ var os11, path13, import_child_process4, buildCliSpawnEnv;
13172
12893
  var init_provider_cli_shared = __esm({
13173
12894
  "../../oss/packages/daemon-core/src/cli-adapters/provider-cli-shared.ts"() {
13174
12895
  "use strict";
@@ -13177,32 +12898,6 @@ var init_provider_cli_shared = __esm({
13177
12898
  import_child_process4 = require("child_process");
13178
12899
  init_spawn_env();
13179
12900
  buildCliSpawnEnv = sanitizeSpawnEnv;
13180
- COMMON_COMPARABLE_WRAP_WORDS = /* @__PURE__ */ new Set([
13181
- "a",
13182
- "an",
13183
- "and",
13184
- "as",
13185
- "at",
13186
- "but",
13187
- "by",
13188
- "for",
13189
- "from",
13190
- "in",
13191
- "into",
13192
- "is",
13193
- "it",
13194
- "of",
13195
- "on",
13196
- "or",
13197
- "that",
13198
- "the",
13199
- "their",
13200
- "then",
13201
- "this",
13202
- "to",
13203
- "was",
13204
- "with"
13205
- ]);
13206
12901
  }
13207
12902
  });
13208
12903
 
@@ -13213,169 +12908,8 @@ function sliceFromOffset(text, start) {
13213
12908
  if (start >= text.length) return "";
13214
12909
  return text.slice(start);
13215
12910
  }
13216
- function hydrateCliParsedMessages(parsedMessages, options) {
13217
- const { committedMessages, scope, lastOutputAt } = options;
13218
- const referenceMessages = [...committedMessages];
13219
- const referenceComparables = new Array(referenceMessages.length);
13220
- const usedReferenceIndexes = /* @__PURE__ */ new Set();
13221
- const now = options.now ?? Date.now();
13222
- let exactReferenceIndexesByKey = null;
13223
- const exactReferenceCursorByKey = /* @__PURE__ */ new Map();
13224
- const hasFiniteTimestamp = (message) => typeof message?.timestamp === "number" && Number.isFinite(message.timestamp);
13225
- const getReferenceComparable = (index) => {
13226
- if (typeof referenceComparables[index] === "string") return referenceComparables[index] || "";
13227
- const comparable = normalizeComparableMessageContent(referenceMessages[index]?.content || "");
13228
- referenceComparables[index] = comparable;
13229
- return comparable;
13230
- };
13231
- const messagesShareStableIdentity = (parsed, reference) => {
13232
- if (!parsed || !reference) return false;
13233
- const parsedId = typeof parsed.id === "string" ? parsed.id.trim() : "";
13234
- const referenceId = typeof reference.id === "string" ? reference.id.trim() : "";
13235
- if (parsedId && referenceId && parsedId === referenceId) return true;
13236
- return typeof parsed.index === "number" && Number.isFinite(parsed.index) && typeof reference.index === "number" && Number.isFinite(reference.index) && parsed.index === reference.index;
13237
- };
13238
- const exactReferenceKey = (role, comparable) => `${role}\0${comparable}`;
13239
- const ensureExactReferenceIndex = () => {
13240
- if (exactReferenceIndexesByKey) return exactReferenceIndexesByKey;
13241
- const byKey = /* @__PURE__ */ new Map();
13242
- for (let i = 0; i < referenceMessages.length; i++) {
13243
- const candidate = referenceMessages[i];
13244
- if (!candidate || candidate.role !== "user" && candidate.role !== "assistant" || !hasFiniteTimestamp(candidate)) continue;
13245
- const comparable = getReferenceComparable(i);
13246
- if (!comparable) continue;
13247
- const key = exactReferenceKey(candidate.role, comparable);
13248
- const indexes = byKey.get(key);
13249
- if (indexes) {
13250
- indexes.push(i);
13251
- } else {
13252
- byKey.set(key, [i]);
13253
- }
13254
- }
13255
- exactReferenceIndexesByKey = byKey;
13256
- return byKey;
13257
- };
13258
- const takeExactReferenceTimestamp = (role, normalizedContent) => {
13259
- const key = exactReferenceKey(role, normalizedContent);
13260
- const indexes = ensureExactReferenceIndex().get(key);
13261
- if (!indexes) return void 0;
13262
- let cursor = exactReferenceCursorByKey.get(key) || 0;
13263
- while (cursor < indexes.length) {
13264
- const candidateIndex = indexes[cursor];
13265
- cursor += 1;
13266
- if (usedReferenceIndexes.has(candidateIndex)) continue;
13267
- const candidate = referenceMessages[candidateIndex];
13268
- if (!candidate || candidate.role !== role || !hasFiniteTimestamp(candidate)) continue;
13269
- usedReferenceIndexes.add(candidateIndex);
13270
- exactReferenceCursorByKey.set(key, cursor);
13271
- return candidate.timestamp;
13272
- }
13273
- exactReferenceCursorByKey.set(key, cursor);
13274
- return void 0;
13275
- };
13276
- const findReferenceTimestamp = (message, role, content, parsedIndex) => {
13277
- const sameIndex = referenceMessages[parsedIndex];
13278
- if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && hasFiniteTimestamp(sameIndex) && messagesShareStableIdentity(message, sameIndex)) {
13279
- usedReferenceIndexes.add(parsedIndex);
13280
- return sameIndex.timestamp;
13281
- }
13282
- const normalizedContent = normalizeComparableMessageContent(content);
13283
- if (!normalizedContent) return void 0;
13284
- if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && getReferenceComparable(parsedIndex) === normalizedContent && hasFiniteTimestamp(sameIndex)) {
13285
- usedReferenceIndexes.add(parsedIndex);
13286
- return sameIndex.timestamp;
13287
- }
13288
- const exactTimestamp = takeExactReferenceTimestamp(role, normalizedContent);
13289
- if (typeof exactTimestamp === "number") return exactTimestamp;
13290
- for (let i = 0; i < referenceMessages.length; i++) {
13291
- if (usedReferenceIndexes.has(i)) continue;
13292
- const candidate = referenceMessages[i];
13293
- if (!candidate || candidate.role !== role) continue;
13294
- const candidateContent = getReferenceComparable(i);
13295
- if (!candidateContent) continue;
13296
- const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
13297
- if (!fuzzyMatch) continue;
13298
- if (hasFiniteTimestamp(candidate)) {
13299
- usedReferenceIndexes.add(i);
13300
- return candidate.timestamp;
13301
- }
13302
- }
13303
- return void 0;
13304
- };
13305
- return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message, index) => {
13306
- const role = message.role;
13307
- const content = typeof message.content === "string" ? message.content : String(message.content || "");
13308
- const parsedTimestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0;
13309
- const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(message, role, content, index);
13310
- const fallbackTimestamp = role === "user" ? scope?.startedAt || now : lastOutputAt || scope?.startedAt || now;
13311
- const timestamp = referenceTimestamp ?? fallbackTimestamp;
13312
- return {
13313
- ...message,
13314
- role,
13315
- content,
13316
- timestamp,
13317
- receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp
13318
- };
13319
- });
13320
- }
13321
- function chooseMoreComparableCliMessage(left2, right2, leftComparable = normalizeComparableMessageContent(left2.content || ""), rightComparable = normalizeComparableMessageContent(right2.content || "")) {
13322
- if (leftComparable && leftComparable === rightComparable) {
13323
- const leftNewlines = String(left2.content || "").split(/\r\n|\n|\r/g).length - 1;
13324
- const rightNewlines = String(right2.content || "").split(/\r\n|\n|\r/g).length - 1;
13325
- return rightNewlines < leftNewlines ? right2 : left2;
13326
- }
13327
- return rightComparable.length > leftComparable.length ? right2 : left2;
13328
- }
13329
- function dedupeConsecutiveComparableCliMessages(messages) {
13330
- const deduped = [];
13331
- for (const message of messages) {
13332
- const current = {
13333
- ...message,
13334
- content: typeof message.content === "string" ? message.content : String(message.content || "")
13335
- };
13336
- const currentComparable = normalizeComparableMessageContent(current.content || "");
13337
- const previous = deduped[deduped.length - 1];
13338
- if (!previous) {
13339
- deduped.push({ message: current, comparable: currentComparable });
13340
- continue;
13341
- }
13342
- const sameRole = previous.message.role === current.role;
13343
- const sameKind = (previous.message.kind || "standard") === (current.kind || "standard");
13344
- const sameSender = (previous.message.senderName || "") === (current.senderName || "");
13345
- const comparableMatch = previous.comparable && previous.comparable === currentComparable;
13346
- if (sameRole && sameKind && sameSender && comparableMatch) {
13347
- const selected = chooseMoreComparableCliMessage(
13348
- previous.message,
13349
- current,
13350
- previous.comparable,
13351
- currentComparable
13352
- );
13353
- deduped[deduped.length - 1] = {
13354
- message: selected,
13355
- comparable: selected === current ? currentComparable : previous.comparable
13356
- };
13357
- continue;
13358
- }
13359
- deduped.push({ message: current, comparable: currentComparable });
13360
- }
13361
- return deduped.map((entry) => entry.message);
13362
- }
13363
- function normalizeCliParsedMessages(parsedMessages, options) {
13364
- return dedupeConsecutiveComparableCliMessages(hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
13365
- role: message.role,
13366
- content: message.content,
13367
- timestamp: message.timestamp,
13368
- receivedAt: message.receivedAt,
13369
- kind: message.kind,
13370
- id: message.id,
13371
- index: message.index,
13372
- providerUnitKey: message.providerUnitKey,
13373
- bubbleId: message.bubbleId,
13374
- bubbleState: message.bubbleState,
13375
- _turnKey: message._turnKey,
13376
- meta: message.meta,
13377
- senderName: message.senderName
13378
- })));
12911
+ function normalizeCliParsedMessages(parsedMessages, _options) {
12912
+ return Array.isArray(parsedMessages) ? parsedMessages : [];
13379
12913
  }
13380
12914
  function buildCliParseInput(options) {
13381
12915
  const {
@@ -13585,40 +13119,8 @@ var provider_cli_adapter_exports = {};
13585
13119
  __export(provider_cli_adapter_exports, {
13586
13120
  ProviderCliAdapter: () => ProviderCliAdapter,
13587
13121
  appendBoundedText: () => appendBoundedText,
13588
- normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime,
13589
- sanitizeCliStandardMessageContent: () => sanitizeCliStandardMessageContent,
13590
- trimLastAssistantEchoForCliMessages: () => trimLastAssistantEchoForCliMessages
13591
- });
13592
- function normalizeComparableTranscriptText(value) {
13593
- return sanitizeTerminalText(String(value || "")).replace(/\s+/g, " ").trim();
13594
- }
13595
- function hasVisibleInterruptPrompt(text) {
13596
- const interruptCopyPattern = /\bEnter\s+to\s+interrupt\b(?:\s*,?\s*Ctrl\s*(?:\+|-)?\s*C\s+to\s+cancel)?/i;
13597
- return sanitizeTerminalText(text || "").split(/\r?\n/g).some((line) => {
13598
- const trimmed = line.trim();
13599
- if (!interruptCopyPattern.test(trimmed)) return false;
13600
- return /^(?:[^A-Za-z0-9\s]{1,8}\s+)?[❯›>]\s+/.test(trimmed);
13601
- });
13602
- }
13603
- function parsedTranscriptIsRicherThanCommitted(parsedMessages, committedMessages) {
13604
- if (!Array.isArray(parsedMessages) || !Array.isArray(committedMessages)) return false;
13605
- if (parsedMessages.length > committedMessages.length) return true;
13606
- if (parsedMessages.length !== committedMessages.length) return false;
13607
- for (let index = 0; index < parsedMessages.length; index += 1) {
13608
- const parsed = parsedMessages[index];
13609
- const committed = committedMessages[index];
13610
- if (!parsed || !committed) return false;
13611
- if ((parsed.role || "") !== (committed.role || "")) return false;
13612
- if (parsed.id && committed.id && String(parsed.id) !== String(committed.id)) return false;
13613
- if (typeof parsed.index === "number" && typeof committed.index === "number" && parsed.index !== committed.index) return false;
13614
- const parsedText = normalizeComparableTranscriptText(parsed.content);
13615
- const committedText = normalizeComparableTranscriptText(committed.content);
13616
- if (!parsedText || !committedText || parsedText === committedText) continue;
13617
- if (parsedText.length > committedText.length && parsedText.startsWith(committedText)) return true;
13618
- return false;
13619
- }
13620
- return false;
13621
- }
13122
+ normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
13123
+ });
13622
13124
  function appendBoundedText(current, chunk, maxChars) {
13623
13125
  if (!chunk) return current.length <= maxChars ? current : current.slice(-maxChars);
13624
13126
  if (maxChars <= 0) return "";
@@ -13627,76 +13129,7 @@ function appendBoundedText(current, chunk, maxChars) {
13627
13129
  if (current.length <= keepFromCurrent) return current + chunk;
13628
13130
  return current.slice(-keepFromCurrent) + chunk;
13629
13131
  }
13630
- function isLikelyCommittedActivityPrefixContinuation(line) {
13631
- const trimmed = String(line || "").trim();
13632
- if (!trimmed) return false;
13633
- if (COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(trimmed)) return false;
13634
- if (/\s/.test(trimmed)) return false;
13635
- if (/[가-힣]/.test(trimmed)) return false;
13636
- if (trimmed.length > 96) return false;
13637
- return /^[A-Za-z0-9_./:@+%=-]+$/.test(trimmed);
13638
- }
13639
- function parseCommittedActivityPrefixBlock(lines, index) {
13640
- const first = String(lines[index] || "").trim();
13641
- if (!COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(first)) return null;
13642
- const parts = [first];
13643
- let nextIndex = index + 1;
13644
- while (nextIndex < lines.length && isLikelyCommittedActivityPrefixContinuation(lines[nextIndex])) {
13645
- parts.push(String(lines[nextIndex] || "").trim());
13646
- nextIndex += 1;
13647
- }
13648
- return { label: parts.join(""), nextIndex };
13649
- }
13650
- function sanitizeCliStandardMessageContent(content) {
13651
- const source = String(content || "").trim();
13652
- if (!source) return "";
13653
- const lines = source.split(/\r?\n/);
13654
- if (lines.length < 4) return source;
13655
- const counts = /* @__PURE__ */ new Map();
13656
- for (let index = 0; index < lines.length; index += 1) {
13657
- const block = parseCommittedActivityPrefixBlock(lines, index);
13658
- if (!block) continue;
13659
- counts.set(block.label, (counts.get(block.label) || 0) + 1);
13660
- index = block.nextIndex - 1;
13661
- }
13662
- const repeatedLabels = new Set(
13663
- Array.from(counts.entries()).filter(([, count]) => count >= 3).map(([label]) => label)
13664
- );
13665
- if (repeatedLabels.size === 0) return source;
13666
- const stripped = [];
13667
- let removed = 0;
13668
- for (let index = 0; index < lines.length; index += 1) {
13669
- const block = parseCommittedActivityPrefixBlock(lines, index);
13670
- if (block && repeatedLabels.has(block.label)) {
13671
- removed += 1;
13672
- index = block.nextIndex - 1;
13673
- continue;
13674
- }
13675
- stripped.push(lines[index]);
13676
- }
13677
- const next = stripped.join("\n").replace(/\n{3,}/g, "\n\n").trim();
13678
- return removed >= 3 && next.length >= 80 ? next : source;
13679
- }
13680
- function sanitizeCommittedMessageForDisplay(message) {
13681
- if (!message || message.role !== "assistant" || (message.kind || "standard") !== "standard") return message;
13682
- const content = sanitizeCliStandardMessageContent(message.content);
13683
- if (content === message.content) return message;
13684
- return { ...message, content };
13685
- }
13686
- function trimLastAssistantEchoForCliMessages(messages, prompt2) {
13687
- if (!prompt2) return;
13688
- for (let index = messages.length - 1; index >= 0; index -= 1) {
13689
- const message = messages[index];
13690
- if (!message || message.role !== "assistant" || typeof message.content !== "string") continue;
13691
- if ((message.kind || "standard") !== "standard") continue;
13692
- message.content = trimPromptEchoPrefix(message.content, prompt2);
13693
- if (!message.content.trim()) {
13694
- messages.splice(index, 1);
13695
- }
13696
- return;
13697
- }
13698
- }
13699
- var os13, COMMITTED_ACTIVITY_PREFIX_BLOCK_RE, ProviderCliAdapter;
13132
+ var os13, ProviderCliAdapter;
13700
13133
  var init_provider_cli_adapter = __esm({
13701
13134
  "../../oss/packages/daemon-core/src/cli-adapters/provider-cli-adapter.ts"() {
13702
13135
  "use strict";
@@ -13706,13 +13139,10 @@ var init_provider_cli_adapter = __esm({
13706
13139
  init_terminal_screen();
13707
13140
  init_pty_transport();
13708
13141
  init_provider_cli_shared();
13709
- init_chat_message_normalization();
13710
- init_read_chat_contract();
13711
13142
  init_provider_cli_parse();
13712
13143
  init_provider_cli_config();
13713
13144
  init_provider_cli_runtime();
13714
13145
  init_provider_cli_shared();
13715
- COMMITTED_ACTIVITY_PREFIX_BLOCK_RE = /^(?:📖|💻|🔎|📚|📋|✏️|📝|🔧|🛠️|⚙️)\s+(.+)$/;
13716
13146
  ProviderCliAdapter = class _ProviderCliAdapter {
13717
13147
  constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
13718
13148
  this.extraArgs = extraArgs;
@@ -13755,11 +13185,6 @@ var init_provider_cli_adapter = __esm({
13755
13185
  provider;
13756
13186
  ptyProcess = null;
13757
13187
  transportFactory;
13758
- messages = [];
13759
- committedMessages = [];
13760
- structuredMessages = [];
13761
- committedMessagesActivitySignature = "";
13762
- committedMessagesChangedAt = 0;
13763
13188
  currentStatus = "starting";
13764
13189
  onStatusChange = null;
13765
13190
  responseBuffer = "";
@@ -13839,11 +13264,8 @@ var init_provider_cli_adapter = __esm({
13839
13264
  traceSeq = 0;
13840
13265
  traceSessionId = "";
13841
13266
  parsedStatusCache = null;
13842
- lastStatusHotPathParseAt = Number.NEGATIVE_INFINITY;
13843
- static STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS = 1e3;
13844
13267
  static SCREEN_SNAPSHOT_MIN_INTERVAL_MS = 250;
13845
13268
  static MAX_TRACE_ENTRIES = 250;
13846
- static PARSE_MESSAGE_TAIL_LIMIT = 100;
13847
13269
  providerResolutionMeta;
13848
13270
  static FINISH_RETRY_DELAY_MS = 300;
13849
13271
  static MAX_FINISH_RETRIES = 2;
@@ -13864,35 +13286,6 @@ var init_provider_cli_adapter = __esm({
13864
13286
  recordBoundedAppendDrop(previousLength, appendedLength, nextLength) {
13865
13287
  return Math.max(0, previousLength + appendedLength - nextLength);
13866
13288
  }
13867
- buildCommittedMessagesActivitySignature() {
13868
- const last = this.committedMessages[this.committedMessages.length - 1];
13869
- return [
13870
- String(this.committedMessages.length),
13871
- String(last?.role || ""),
13872
- String(last?.kind || ""),
13873
- String(last?.senderName || ""),
13874
- String(last?.timestamp || ""),
13875
- String(last?.receivedAt || ""),
13876
- normalizeComparableMessageContent(last?.content || "").slice(-240)
13877
- ].join("|");
13878
- }
13879
- syncMessageViews() {
13880
- const signature = this.buildCommittedMessagesActivitySignature();
13881
- if (signature !== this.committedMessagesActivitySignature) {
13882
- this.committedMessagesActivitySignature = signature;
13883
- this.committedMessagesChangedAt = Date.now();
13884
- }
13885
- this.messages = [...this.committedMessages];
13886
- this.structuredMessages = [...this.committedMessages];
13887
- }
13888
- getLastCommittedMessageActivityAt() {
13889
- const last = this.committedMessages[this.committedMessages.length - 1];
13890
- const messageTime = Math.max(
13891
- typeof last?.receivedAt === "number" && Number.isFinite(last.receivedAt) ? last.receivedAt : 0,
13892
- typeof last?.timestamp === "number" && Number.isFinite(last.timestamp) ? last.timestamp : 0
13893
- );
13894
- return Math.max(messageTime, this.committedMessagesChangedAt || 0);
13895
- }
13896
13289
  readTerminalScreenText(now = Date.now()) {
13897
13290
  const screenText = this.terminalScreen.getText() || "";
13898
13291
  this.lastScreenText = screenText;
@@ -13912,7 +13305,7 @@ var init_provider_cli_adapter = __esm({
13912
13305
  }
13913
13306
  getFreshParsedStatusCache() {
13914
13307
  const cached2 = this.parsedStatusCache;
13915
- if (cached2 && cached2.committedMessagesRef === this.committedMessages && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.screenText === this.lastScreenText && cached2.currentStatus === this.currentStatus && cached2.activeModal === this.activeModal && cached2.cliName === this.cliName) {
13308
+ if (cached2 && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.screenText === this.lastScreenText && cached2.currentStatus === this.currentStatus && cached2.activeModal === this.activeModal && cached2.cliName === this.cliName) {
13916
13309
  return cached2.result;
13917
13310
  }
13918
13311
  return null;
@@ -13923,45 +13316,6 @@ var init_provider_cli_adapter = __esm({
13923
13316
  shouldUseFullProviderTranscriptContext() {
13924
13317
  return this.providerOwnsTranscript() && this.provider.transcriptContext === "full";
13925
13318
  }
13926
- selectParseBaseMessages(baseMessages) {
13927
- if (this.shouldUseFullProviderTranscriptContext()) return baseMessages;
13928
- if (baseMessages.length <= _ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
13929
- return baseMessages.slice(-_ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
13930
- }
13931
- messagesShareStableIdentity(left2, right2) {
13932
- if (left2 === right2) return true;
13933
- if (!left2 || !right2) return false;
13934
- if ((left2.role || "") !== (right2.role || "")) return false;
13935
- if (left2.id && right2.id && String(left2.id) === String(right2.id)) return true;
13936
- if (typeof left2.index === "number" && typeof right2.index === "number" && left2.index === right2.index) return true;
13937
- return false;
13938
- }
13939
- messagesComparable(left2, right2) {
13940
- if (this.messagesShareStableIdentity(left2, right2)) return true;
13941
- if (!left2 || !right2) return false;
13942
- if ((left2.role || "") !== (right2.role || "")) return false;
13943
- const leftText = normalizeComparableTranscriptText(left2.content);
13944
- const rightText = normalizeComparableTranscriptText(right2.content);
13945
- return !!leftText && leftText === rightText;
13946
- }
13947
- stitchParsedMessagesWithCommittedBase(parsedMessages, fullBaseMessages, parseBaseMessages) {
13948
- if (!Array.isArray(parsedMessages) || parsedMessages.length === 0) return parsedMessages;
13949
- if (fullBaseMessages.length <= parseBaseMessages.length) return parsedMessages;
13950
- const parsedFirst = parsedMessages[0];
13951
- const fullFirst = fullBaseMessages[0];
13952
- if (parsedMessages.length >= fullBaseMessages.length && this.messagesComparable(parsedFirst, fullFirst)) {
13953
- return parsedMessages;
13954
- }
13955
- const tailFirst = parseBaseMessages[0];
13956
- if (tailFirst && this.messagesComparable(parsedFirst, tailFirst)) {
13957
- const prefixLength = fullBaseMessages.length - parseBaseMessages.length;
13958
- const prefix = fullBaseMessages.slice(0, prefixLength);
13959
- const shouldSanitizePrefix = !!this.currentTurnScope || this.currentStatus !== "idle" || !!this.activeModal;
13960
- const nextPrefix = shouldSanitizePrefix ? prefix.map((message) => sanitizeCommittedMessageForDisplay(message)) : prefix;
13961
- return [...nextPrefix, ...parsedMessages];
13962
- }
13963
- return [...fullBaseMessages, ...parsedMessages];
13964
- }
13965
13319
  getIdleFinishConfirmMs() {
13966
13320
  return this.timeouts.idleFinishConfirm;
13967
13321
  }
@@ -14414,9 +13768,6 @@ var init_provider_cli_adapter = __esm({
14414
13768
  `[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(summarizeCliTraceText(finalScreenText, 240)).slice(0, 280)}`
14415
13769
  );
14416
13770
  }
14417
- trimLastAssistantEcho(messages, prompt2) {
14418
- trimLastAssistantEchoForCliMessages(messages, prompt2);
14419
- }
14420
13771
  clearAllTimers() {
14421
13772
  if (this.responseTimeout) {
14422
13773
  clearTimeout(this.responseTimeout);
@@ -14512,10 +13863,10 @@ var init_provider_cli_adapter = __esm({
14512
13863
  }
14513
13864
  const session = this.runParseSession();
14514
13865
  if (!session) return;
14515
- const { status, messages, modal, parsedStatus } = session;
13866
+ const { status, messages, parsedStatus } = session;
13867
+ const modal = session.activeModal ?? session.modal ?? null;
14516
13868
  const parsedMessages = normalizeCliParsedMessages(messages, {
14517
- committedMessages: this.committedMessages,
14518
- scope: this.currentTurnScope,
13869
+ scope: null,
14519
13870
  lastOutputAt: this.lastOutputAt
14520
13871
  });
14521
13872
  if (this.maybeCommitVisibleIdleTranscript(session, parsedMessages)) return;
@@ -14695,7 +14046,7 @@ var init_provider_cli_adapter = __esm({
14695
14046
  const effectiveScreenText = screenText || this.accumulatedBuffer;
14696
14047
  const noActiveTurn = !this.currentTurnScope;
14697
14048
  const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(effectiveScreenText);
14698
- const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant && parsedMessages.length > this.committedMessages.length;
14049
+ const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant;
14699
14050
  if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
14700
14051
  return;
14701
14052
  }
@@ -14852,10 +14203,7 @@ var init_provider_cli_adapter = __esm({
14852
14203
  }
14853
14204
  const visibleAssistant = [...parsedMessages].reverse().find((m) => m.role === "assistant" && m.content.trim());
14854
14205
  if (!visibleAssistant) return false;
14855
- this.committedMessages = parsedMessages;
14856
- this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
14857
14206
  this.clearAllTimers();
14858
- this.syncMessageViews();
14859
14207
  this.responseBuffer = "";
14860
14208
  this.isWaitingForResponse = false;
14861
14209
  this.responseSettleIgnoreUntil = 0;
@@ -14867,37 +14215,34 @@ var init_provider_cli_adapter = __esm({
14867
14215
  this.setStatus("idle", "script_idle_commit");
14868
14216
  this.onStatusChange?.();
14869
14217
  this.recordTrace("script_idle_commit", {
14870
- messageCount: this.committedMessages.length,
14218
+ messageCount: parsedMessages.length,
14871
14219
  lastAssistant: summarizeCliTraceText(visibleAssistant.content, 320)
14872
14220
  });
14873
14221
  return true;
14874
14222
  }
14875
14223
  commitCurrentTranscript() {
14876
14224
  const parsed = this.parseCurrentTranscript(
14877
- this.committedMessages,
14225
+ [],
14878
14226
  this.responseBuffer,
14879
14227
  this.currentTurnScope
14880
14228
  );
14881
14229
  if (parsed && Array.isArray(parsed.messages)) {
14882
- this.committedMessages = normalizeCliParsedMessages(parsed.messages, {
14883
- committedMessages: this.committedMessages,
14884
- scope: this.currentTurnScope,
14230
+ const parsedMessages = normalizeCliParsedMessages(parsed.messages, {
14231
+ scope: null,
14885
14232
  lastOutputAt: this.lastOutputAt
14886
14233
  });
14887
- this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
14888
- this.syncMessageViews();
14889
- const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
14234
+ const lastAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
14890
14235
  if (this.currentTurnScope) {
14891
14236
  LOG.info(
14892
14237
  "CLI",
14893
- `[${this.cliType}] commitCurrentTranscript committedMessages=${this.committedMessages.length} finalLastAssistant=${JSON.stringify(summarizeCliTraceText(lastAssistant?.content || "", 220)).slice(0, 260)}`
14238
+ `[${this.cliType}] commitCurrentTranscript parserMessages=${parsedMessages.length} finalLastAssistant=${JSON.stringify(summarizeCliTraceText(lastAssistant?.content || "", 220)).slice(0, 260)}`
14894
14239
  );
14895
14240
  }
14896
14241
  this.recordTrace("commit_transcript", {
14897
14242
  parsedStatus: parsed.status || null,
14898
- messageCount: this.committedMessages.length,
14243
+ messageCount: parsedMessages.length,
14899
14244
  lastAssistant: lastAssistant ? summarizeCliTraceText(lastAssistant.content, 320) : "",
14900
- messages: summarizeCliTraceMessages(this.committedMessages),
14245
+ messages: summarizeCliTraceMessages(parsedMessages),
14901
14246
  ...buildCliTraceParseSnapshot({
14902
14247
  accumulatedBuffer: this.accumulatedBuffer,
14903
14248
  accumulatedRawBuffer: this.accumulatedRawBuffer,
@@ -14931,63 +14276,31 @@ var init_provider_cli_adapter = __esm({
14931
14276
  }
14932
14277
  // ─── Script Execution ──────────────────────────
14933
14278
  runParseSession() {
14934
- if (typeof this.cliScripts?.parseSession === "function") {
14935
- try {
14936
- const screenText = this.terminalScreen.getText();
14937
- const tail = this.recentOutputBuffer.slice(-500);
14938
- const parseBaseMessages = this.selectParseBaseMessages(this.committedMessages);
14939
- const input = buildCliParseInput({
14940
- accumulatedBuffer: this.accumulatedBuffer,
14941
- accumulatedRawBuffer: this.accumulatedRawBuffer,
14942
- recentOutputBuffer: this.recentOutputBuffer,
14943
- terminalScreenText: screenText,
14944
- baseMessages: parseBaseMessages,
14945
- partialResponse: this.responseBuffer,
14946
- isWaitingForResponse: this.isWaitingForResponse,
14947
- scope: this.currentTurnScope,
14948
- runtimeSettings: this.runtimeSettings
14949
- });
14950
- const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
14951
- if (session && typeof session === "object" && Array.isArray(session.messages)) {
14952
- session.messages = this.stitchParsedMessagesWithCommittedBase(
14953
- session.messages,
14954
- this.committedMessages,
14955
- parseBaseMessages
14956
- );
14957
- }
14958
- this.parseErrorMessage = null;
14959
- return session && typeof session === "object" ? session : null;
14960
- } catch (e) {
14961
- const message = e?.message || String(e);
14962
- this.parseErrorMessage = message;
14963
- LOG.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
14964
- return null;
14965
- }
14279
+ if (typeof this.cliScripts?.parseSession !== "function") {
14280
+ this.parseErrorMessage = `${this.cliType} parseSession unavailable`;
14281
+ return null;
14966
14282
  }
14967
- if (!this.cliScripts?.detectStatus && !this.cliScripts?.parseOutput) return null;
14968
14283
  try {
14969
- const tail = this.settledBuffer;
14970
- const parsedTranscript = this.parseCurrentTranscript(
14971
- this.committedMessages,
14972
- this.responseBuffer,
14973
- this.currentTurnScope
14974
- );
14975
- const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((b) => typeof b === "string" && b.trim()) ? parsedTranscript.activeModal : null;
14976
- const approval = this.runParseApproval(tail);
14977
- const modal = approval || parsedModal;
14978
- const rawStatus = this.runDetectStatus(tail);
14979
- const parsedStatus = typeof parsedTranscript?.status === "string" ? parsedTranscript.status : null;
14980
- const effectiveStatus = parsedStatus === "waiting_approval" && modal ? "waiting_approval" : rawStatus || parsedStatus || "idle";
14981
- return {
14982
- status: effectiveStatus,
14983
- messages: Array.isArray(parsedTranscript?.messages) ? parsedTranscript.messages : [],
14984
- modal,
14985
- parsedStatus
14986
- };
14284
+ const screenText = this.terminalScreen.getText();
14285
+ const tail = this.recentOutputBuffer.slice(-500);
14286
+ const input = buildCliParseInput({
14287
+ accumulatedBuffer: this.accumulatedBuffer,
14288
+ accumulatedRawBuffer: this.accumulatedRawBuffer,
14289
+ recentOutputBuffer: this.recentOutputBuffer,
14290
+ terminalScreenText: screenText,
14291
+ baseMessages: [],
14292
+ partialResponse: this.responseBuffer,
14293
+ isWaitingForResponse: this.isWaitingForResponse,
14294
+ scope: this.currentTurnScope,
14295
+ runtimeSettings: this.runtimeSettings
14296
+ });
14297
+ const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
14298
+ this.parseErrorMessage = null;
14299
+ return session && typeof session === "object" ? session : null;
14987
14300
  } catch (e) {
14988
14301
  const message = e?.message || String(e);
14989
14302
  this.parseErrorMessage = message;
14990
- LOG.warn("CLI", `[${this.cliType}] parseSession fallback error: ${message}`);
14303
+ LOG.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
14991
14304
  return null;
14992
14305
  }
14993
14306
  }
@@ -15037,45 +14350,14 @@ var init_provider_cli_adapter = __esm({
15037
14350
  if (this.isWaitingForResponse && this.currentTurnScope && this.currentStatus !== "stopped") return "generating";
15038
14351
  return this.currentStatus;
15039
14352
  }
15040
- suppressStaleParsedApproval(parsed, recentBuffer, screenText) {
15041
- const actionableParsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
15042
- if (!parsed || parsed?.status !== "waiting_approval" || !actionableParsedModal) {
15043
- return parsed;
15044
- }
15045
- const inApprovalCooldown = this.lastApprovalResolvedAt > 0 && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
15046
- if (!inApprovalCooldown) {
15047
- return parsed;
15048
- }
15049
- const visibleModal = this.runParseApproval(recentBuffer);
15050
- if (visibleModal) {
15051
- return parsed;
15052
- }
15053
- const detectedStatus = this.runDetectStatus(recentBuffer);
15054
- const resolvedStatus = detectedStatus && detectedStatus !== "waiting_approval" ? detectedStatus : this.isWaitingForResponse || this.currentTurnScope ? "generating" : this.currentStatus === "waiting_approval" ? "idle" : this.currentStatus;
15055
- return {
15056
- ...parsed,
15057
- status: resolvedStatus,
15058
- activeModal: null
15059
- };
15060
- }
15061
14353
  // ─── Public API (CliAdapter) ───────────────────
15062
14354
  getStatus(options = {}) {
15063
14355
  const allowParse = options.allowParse !== false;
15064
14356
  const startupModal = allowParse && this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
15065
14357
  let effectiveStatus = this.projectEffectiveStatus(startupModal);
15066
14358
  let effectiveModal = startupModal || this.activeModal;
15067
- if (allowParse && !startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
15068
- let parsed = this.getFreshParsedStatusCache();
15069
- if (!parsed && effectiveStatus !== "idle") {
15070
- const now = Date.now();
15071
- if (now - this.lastStatusHotPathParseAt >= _ProviderCliAdapter.STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS) {
15072
- this.lastStatusHotPathParseAt = now;
15073
- try {
15074
- parsed = this.getScriptParsedStatus();
15075
- } catch {
15076
- }
15077
- }
15078
- }
14359
+ if (allowParse && !startupModal && !effectiveModal) {
14360
+ const parsed = this.getFreshParsedStatusCache();
15079
14361
  const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
15080
14362
  if (parsed?.status === "waiting_approval" && parsedModal) {
15081
14363
  effectiveStatus = "waiting_approval";
@@ -15085,7 +14367,7 @@ var init_provider_cli_adapter = __esm({
15085
14367
  const bufferState = this.getBufferState();
15086
14368
  return {
15087
14369
  status: effectiveStatus,
15088
- messages: [...this.committedMessages],
14370
+ messages: [],
15089
14371
  workingDir: this.workingDir,
15090
14372
  activeModal: effectiveModal,
15091
14373
  errorMessage: this.parseErrorMessage || void 0,
@@ -15093,98 +14375,6 @@ var init_provider_cli_adapter = __esm({
15093
14375
  ...bufferState ? { bufferState } : {}
15094
14376
  };
15095
14377
  }
15096
- seedCommittedMessages(messages) {
15097
- const normalized = (Array.isArray(messages) ? messages : []).filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
15098
- role: message.role,
15099
- content: typeof message.content === "string" ? message.content : String(message.content || ""),
15100
- timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0,
15101
- receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : void 0,
15102
- kind: typeof message.kind === "string" ? message.kind : void 0,
15103
- id: typeof message.id === "string" ? message.id : void 0,
15104
- index: typeof message.index === "number" ? message.index : void 0,
15105
- providerUnitKey: typeof message.providerUnitKey === "string" ? message.providerUnitKey : void 0,
15106
- bubbleId: typeof message.bubbleId === "string" ? message.bubbleId : void 0,
15107
- bubbleState: typeof message.bubbleState === "string" ? message.bubbleState : void 0,
15108
- _turnKey: typeof message._turnKey === "string" ? message._turnKey : void 0,
15109
- meta: message.meta && typeof message.meta === "object" ? { ...message.meta } : void 0,
15110
- senderName: typeof message.senderName === "string" ? message.senderName : void 0
15111
- }));
15112
- this.committedMessages = normalized;
15113
- this.syncMessageViews();
15114
- }
15115
- getSharedCommittedPrefixLength(parsedMessages) {
15116
- const committedMessages = this.committedMessages;
15117
- const max = Math.min(parsedMessages.length, committedMessages.length);
15118
- let index = 0;
15119
- while (index < max && this.messagesShareStableIdentity(parsedMessages[index], committedMessages[index])) {
15120
- index += 1;
15121
- }
15122
- return index;
15123
- }
15124
- hydrateCommittedPrefixForParsedStatus(parsedMessages) {
15125
- const sharedPrefixLength = this.getSharedCommittedPrefixLength(parsedMessages);
15126
- if (sharedPrefixLength !== this.committedMessages.length) return null;
15127
- const committedHydratedMessages = this.committedMessages.map((message, index) => {
15128
- const timestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : this.lastOutputAt || this.currentTurnScope?.startedAt || Date.now();
15129
- const contentValue = message.content;
15130
- return {
15131
- role: message.role,
15132
- content: typeof contentValue === "string" ? contentValue : String(contentValue || ""),
15133
- timestamp,
15134
- receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp,
15135
- kind: message.kind,
15136
- id: message.id || `msg_${index}`,
15137
- index: typeof message.index === "number" ? message.index : index,
15138
- providerUnitKey: message.providerUnitKey,
15139
- bubbleId: message.bubbleId,
15140
- bubbleState: message.bubbleState,
15141
- _turnKey: message._turnKey,
15142
- meta: message.meta,
15143
- senderName: message.senderName
15144
- };
15145
- });
15146
- const extraMessages = parsedMessages.slice(sharedPrefixLength);
15147
- if (extraMessages.length === 0) return committedHydratedMessages;
15148
- const extraHydratedMessages = hydrateCliParsedMessages(extraMessages, {
15149
- committedMessages: [],
15150
- scope: this.currentTurnScope,
15151
- lastOutputAt: this.lastOutputAt
15152
- }).map((message, offset) => ({
15153
- ...message,
15154
- id: message.id || `msg_${sharedPrefixLength + offset}`,
15155
- index: typeof message.index === "number" ? message.index : sharedPrefixLength + offset
15156
- }));
15157
- return [...committedHydratedMessages, ...extraHydratedMessages];
15158
- }
15159
- hydrateParsedMessagesForStatus(parsedMessages) {
15160
- return this.hydrateCommittedPrefixForParsedStatus(parsedMessages) || hydrateCliParsedMessages(parsedMessages, {
15161
- committedMessages: this.committedMessages,
15162
- scope: this.currentTurnScope,
15163
- lastOutputAt: this.lastOutputAt
15164
- });
15165
- }
15166
- buildCommittedChatMessages() {
15167
- return this.committedMessages.map((message, index) => {
15168
- const rawContentValue = message.content;
15169
- const rawContent = typeof rawContentValue === "string" ? rawContentValue : String(rawContentValue || "");
15170
- const content = message.role === "assistant" && (message.kind || "standard") === "standard" ? sanitizeCliStandardMessageContent(rawContent) : rawContent;
15171
- return buildChatMessage({
15172
- role: message.role,
15173
- content,
15174
- timestamp: message.timestamp,
15175
- kind: message.kind,
15176
- meta: message.meta,
15177
- senderName: message.senderName,
15178
- id: message.id || `msg_${index}`,
15179
- index: typeof message.index === "number" ? message.index : index,
15180
- providerUnitKey: message.providerUnitKey,
15181
- bubbleId: message.bubbleId,
15182
- bubbleState: message.bubbleState,
15183
- _turnKey: message._turnKey,
15184
- receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
15185
- });
15186
- });
15187
- }
15188
14378
  /**
15189
14379
  * Script-based full parse — returns ReadChatResult.
15190
14380
  * Called by command handler / dashboard for rich content rendering.
@@ -15192,125 +14382,30 @@ var init_provider_cli_adapter = __esm({
15192
14382
  getScriptParsedStatus() {
15193
14383
  const screenText = this.readTerminalScreenText();
15194
14384
  const cached2 = this.parsedStatusCache;
15195
- if (cached2 && cached2.committedMessagesRef === this.committedMessages && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.screenText === screenText && cached2.currentStatus === this.currentStatus && cached2.activeModal === this.activeModal && cached2.cliName === this.cliName) {
14385
+ if (cached2 && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.screenText === screenText && cached2.currentStatus === this.currentStatus && cached2.activeModal === this.activeModal && cached2.cliName === this.cliName) {
15196
14386
  return cached2.result;
15197
14387
  }
15198
- const parsed = this.parseCurrentTranscript(
15199
- this.committedMessages,
15200
- this.responseBuffer,
15201
- this.currentTurnScope,
15202
- screenText
15203
- );
15204
- const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
15205
- if (parsedModal && parsed?.status === "waiting_approval") {
15206
- this.activeModal = parsedModal;
15207
- this.isWaitingForResponse = true;
15208
- if (this.currentStatus !== "waiting_approval") {
15209
- this.setStatus("waiting_approval", "parsed_waiting_approval");
15210
- this.onStatusChange?.();
15211
- }
14388
+ const parsed = this.runParseSession();
14389
+ if (!parsed || !Array.isArray(parsed.messages)) {
14390
+ throw new Error(this.parseErrorMessage || `${this.cliType} parseSession did not return messages`);
15212
14391
  }
15213
- if (parsed && Array.isArray(parsed.messages) && this.provider.allowInputDuringGeneration === true) {
15214
- const hydratedForCommit = normalizeCliParsedMessages(parsed.messages, {
15215
- committedMessages: this.committedMessages,
15216
- scope: this.currentTurnScope,
14392
+ const activeModal = parsed.activeModal ?? parsed.modal ?? null;
14393
+ const bufferState = this.getBufferState();
14394
+ const result = {
14395
+ id: parsed.id || "cli_session",
14396
+ status: parsed.status || this.currentStatus,
14397
+ title: parsed.title || this.cliName,
14398
+ messages: normalizeCliParsedMessages(parsed.messages, {
14399
+ scope: null,
15217
14400
  lastOutputAt: this.lastOutputAt
15218
- });
15219
- const fakeSession = {
15220
- status: parsed.status || "idle",
15221
- messages: parsed.messages,
15222
- modal: parsedModal,
15223
- parsedStatus: parsed.status || null
15224
- };
15225
- if (this.maybeCommitVisibleIdleTranscript(fakeSession, hydratedForCommit)) {
15226
- return this.getScriptParsedStatus();
15227
- }
15228
- }
15229
- const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
15230
- let result;
15231
- if (parsed && Array.isArray(parsed.messages)) {
15232
- const parsedHydratedMessages = this.hydrateParsedMessagesForStatus(parsed.messages);
15233
- const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === "assistant" && typeof message.content === "string" && message.content.trim());
15234
- const shouldAdoptParsedIdleReplay = !this.currentTurnScope && !this.activeModal && !!parsedLastAssistant && parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages, this.committedMessages) && (this.currentStatus === "idle" || this.currentStatus === "generating" && this.isWaitingForResponse && parsed.status === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle");
15235
- if (shouldAdoptParsedIdleReplay) {
15236
- this.committedMessages = this.getSharedCommittedPrefixLength(parsed.messages) === this.committedMessages.length ? parsedHydratedMessages.map((message) => ({
15237
- role: message.role,
15238
- content: typeof message.content === "string" ? message.content : String(message.content || ""),
15239
- timestamp: message.timestamp,
15240
- receivedAt: message.receivedAt,
15241
- kind: message.kind,
15242
- id: message.id,
15243
- index: message.index,
15244
- meta: message.meta,
15245
- senderName: message.senderName
15246
- })) : normalizeCliParsedMessages(parsed.messages, {
15247
- committedMessages: this.committedMessages,
15248
- scope: this.currentTurnScope,
15249
- lastOutputAt: this.lastOutputAt
15250
- });
15251
- this.syncMessageViews();
15252
- if (this.currentStatus !== "idle" || this.isWaitingForResponse) {
15253
- this.responseBuffer = "";
15254
- this.isWaitingForResponse = false;
15255
- this.responseSettleIgnoreUntil = 0;
15256
- this.submitRetryUsed = false;
15257
- this.submitRetryPromptSnippet = "";
15258
- this.finishRetryCount = 0;
15259
- this.currentTurnScope = null;
15260
- this.activeModal = null;
15261
- this.setStatus("idle", "parsed_idle_replay_commit");
15262
- this.onStatusChange?.();
15263
- }
15264
- }
15265
- const shouldPreferCommittedHistoryReplay = !this.currentTurnScope && !this.activeModal && this.committedMessages.length > parsedHydratedMessages.length;
15266
- const shouldPreferCommittedIdleReplay = shouldPreferCommittedMessages && !shouldAdoptParsedIdleReplay;
15267
- const hydratedMessages = shouldPreferCommittedIdleReplay || shouldPreferCommittedHistoryReplay ? this.buildCommittedChatMessages() : parsedHydratedMessages;
15268
- result = {
15269
- id: parsed.id || "cli_session",
15270
- status: parsed.status || this.currentStatus,
15271
- title: parsed.title || this.cliName,
15272
- messages: hydratedMessages,
15273
- activeModal: parsed.activeModal ?? this.activeModal,
15274
- providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
15275
- ...this.getBufferState() ? { bufferState: this.getBufferState() } : {},
15276
- ...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
15277
- };
15278
- } else {
15279
- const messages = [...this.committedMessages];
15280
- const bufferState = this.getBufferState();
15281
- result = {
15282
- id: "cli_session",
15283
- status: this.currentStatus,
15284
- title: this.cliName,
15285
- messages: messages.map((message, index) => buildChatMessage({
15286
- ...message,
15287
- id: message.id || `msg_${index}`,
15288
- index: typeof message.index === "number" ? message.index : index,
15289
- receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
15290
- })),
15291
- activeModal: this.activeModal,
15292
- ...bufferState ? { bufferState } : {}
15293
- };
15294
- }
15295
- const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
15296
- const shouldClampStaleGeneratingToIdle = result?.status === "generating" && this.currentStatus === "idle" && !this.currentTurnScope && !result?.activeModal && hasVisibleAssistantMessage && !hasVisibleInterruptPrompt(screenText);
15297
- if (shouldClampStaleGeneratingToIdle) {
15298
- result = {
15299
- ...result,
15300
- status: "idle",
15301
- messages: Array.isArray(result.messages) ? result.messages.map((message) => {
15302
- if (message?.role !== "assistant" || !message?.meta?.streaming) return message;
15303
- const nextMeta = { ...message.meta || {} };
15304
- delete nextMeta.streaming;
15305
- return {
15306
- ...message,
15307
- ...Object.keys(nextMeta).length > 0 ? { meta: nextMeta } : { meta: void 0 }
15308
- };
15309
- }) : result.messages
15310
- };
15311
- }
14401
+ }),
14402
+ activeModal,
14403
+ providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
14404
+ ...bufferState ? { bufferState } : {},
14405
+ ...parsed.transcriptAuthority === "provider" || parsed.transcriptAuthority === "daemon" ? { transcriptAuthority: parsed.transcriptAuthority } : this.providerOwnsTranscript() ? { transcriptAuthority: "provider" } : {},
14406
+ ...parsed.coverage === "full" || parsed.coverage === "tail" || parsed.coverage === "current-turn" ? { coverage: parsed.coverage } : this.providerOwnsTranscript() ? { coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
14407
+ };
15312
14408
  this.parsedStatusCache = {
15313
- committedMessagesRef: this.committedMessages,
15314
14409
  responseBuffer: this.responseBuffer,
15315
14410
  currentTurnScope: this.currentTurnScope,
15316
14411
  recentOutputBuffer: this.recentOutputBuffer,
@@ -15333,7 +14428,7 @@ var init_provider_cli_adapter = __esm({
15333
14428
  accumulatedRawBuffer: this.accumulatedRawBuffer,
15334
14429
  recentOutputBuffer: this.recentOutputBuffer,
15335
14430
  terminalScreenText: this.terminalScreen.getText(),
15336
- baseMessages: this.committedMessages,
14431
+ baseMessages: [],
15337
14432
  partialResponse: this.responseBuffer,
15338
14433
  isWaitingForResponse: this.isWaitingForResponse,
15339
14434
  scope: this.currentTurnScope,
@@ -15344,46 +14439,8 @@ var init_provider_cli_adapter = __esm({
15344
14439
  args: args && typeof args === "object" ? { ...args } : {}
15345
14440
  }));
15346
14441
  }
15347
- parseCurrentTranscript(baseMessages, partialResponse, scope, screenTextOverride) {
15348
- if (!this.cliScripts?.parseOutput) {
15349
- this.parseErrorMessage = null;
15350
- return null;
15351
- }
15352
- try {
15353
- const screenText = typeof screenTextOverride === "string" ? screenTextOverride : this.terminalScreen.getText();
15354
- const parseBaseMessages = this.selectParseBaseMessages(baseMessages);
15355
- const input = buildCliParseInput({
15356
- accumulatedBuffer: this.accumulatedBuffer,
15357
- accumulatedRawBuffer: this.accumulatedRawBuffer,
15358
- recentOutputBuffer: this.recentOutputBuffer,
15359
- terminalScreenText: screenText,
15360
- baseMessages: parseBaseMessages,
15361
- partialResponse,
15362
- isWaitingForResponse: this.isWaitingForResponse,
15363
- scope,
15364
- runtimeSettings: this.runtimeSettings
15365
- });
15366
- const parsed = this.cliScripts.parseOutput(input);
15367
- if (parsed && typeof parsed === "object") {
15368
- Object.assign(parsed, validateReadChatResultPayload(parsed, `${this.cliType} parseOutput`));
15369
- }
15370
- const normalizedParsed = this.suppressStaleParsedApproval(parsed, input.recentBuffer, input.screenText);
15371
- if (normalizedParsed && Array.isArray(normalizedParsed.messages)) {
15372
- normalizedParsed.messages = this.stitchParsedMessagesWithCommittedBase(
15373
- normalizedParsed.messages,
15374
- baseMessages,
15375
- parseBaseMessages
15376
- );
15377
- this.trimLastAssistantEcho(normalizedParsed.messages, scope?.prompt || getLastUserPromptText(baseMessages));
15378
- }
15379
- this.parseErrorMessage = null;
15380
- return normalizedParsed;
15381
- } catch (e) {
15382
- const message = e?.message || String(e);
15383
- this.parseErrorMessage = message;
15384
- LOG.warn("CLI", `[${this.cliType}] parseOutput error: ${message}`);
15385
- throw e;
15386
- }
14442
+ parseCurrentTranscript(_baseMessages, _partialResponse, _scope, _screenTextOverride) {
14443
+ return this.runParseSession();
15387
14444
  }
15388
14445
  /** Whether this adapter has CLI scripts loaded */
15389
14446
  hasCliScripts() {
@@ -15445,8 +14502,6 @@ var init_provider_cli_adapter = __esm({
15445
14502
  commitSendUserTurn(state) {
15446
14503
  if (state.didCommitUserTurn) return;
15447
14504
  state.didCommitUserTurn = true;
15448
- this.committedMessages.push({ role: "user", content: state.text, timestamp: Date.now() });
15449
- this.syncMessageViews();
15450
14505
  }
15451
14506
  armResponseTimeout() {
15452
14507
  if (this.responseTimeout) clearTimeout(this.responseTimeout);
@@ -15638,11 +14693,6 @@ var init_provider_cli_adapter = __esm({
15638
14693
  }
15639
14694
  })() : null;
15640
14695
  const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
15641
- const parsedMessagesBeforeSend = Array.isArray(parsedStatusBeforeSend?.messages) ? parsedStatusBeforeSend.messages.filter((message) => message && (message.role === "user" || message.role === "assistant")) : [];
15642
- const shouldCommitParsedIdleBeforeSend = !allowInputDuringGeneration && parsedSessionStatus === "idle" && parsedMessagesBeforeSend.length > this.committedMessages.length && parsedMessagesBeforeSend.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
15643
- if (shouldCommitParsedIdleBeforeSend) {
15644
- this.commitCurrentTranscript();
15645
- }
15646
14696
  if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
15647
14697
  throw new Error(`${this.cliName} is still processing the previous prompt`);
15648
14698
  }
@@ -15748,9 +14798,6 @@ var init_provider_cli_adapter = __esm({
15748
14798
  activeModal: this.activeModal,
15749
14799
  parseErrorMessage: this.parseErrorMessage,
15750
14800
  messageCounts: {
15751
- committed: this.committedMessages.length,
15752
- structured: this.structuredMessages.length,
15753
- visible: this.messages.length,
15754
14801
  parsedCache: Array.isArray(parsedResult?.messages) ? parsedResult.messages.length : void 0
15755
14802
  },
15756
14803
  buffers: {
@@ -15801,8 +14848,7 @@ var init_provider_cli_adapter = __esm({
15801
14848
  responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
15802
14849
  responseEpoch: this.responseEpoch,
15803
14850
  resizeSuppressUntil: this.resizeSuppressUntil,
15804
- lastApprovalResolvedAt: this.lastApprovalResolvedAt,
15805
- committedMessagesChangedAt: this.committedMessagesChangedAt
14851
+ lastApprovalResolvedAt: this.lastApprovalResolvedAt
15806
14852
  },
15807
14853
  finish: {
15808
14854
  idleFinishCandidate: this.idleFinishCandidate,
@@ -15927,8 +14973,6 @@ var init_provider_cli_adapter = __esm({
15927
14973
  }
15928
14974
  clearHistory() {
15929
14975
  this.clearIdleFinishCandidate("clear_history");
15930
- this.committedMessages = [];
15931
- this.syncMessageViews();
15932
14976
  this.accumulatedBuffer = "";
15933
14977
  this.accumulatedRawBuffer = "";
15934
14978
  this.currentTurnScope = null;
@@ -15969,7 +15013,7 @@ var init_provider_cli_adapter = __esm({
15969
15013
  }
15970
15014
  resolveModal(buttonIndex) {
15971
15015
  let modal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
15972
- if (!modal && typeof this.cliScripts?.parseOutput === "function") {
15016
+ if (!modal && typeof this.cliScripts?.parseSession === "function") {
15973
15017
  try {
15974
15018
  const parsed = this.getScriptParsedStatus();
15975
15019
  const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
@@ -16036,10 +15080,8 @@ var init_provider_cli_adapter = __esm({
16036
15080
  startupParseGate: this.startupParseGate,
16037
15081
  spawnAt: this.spawnAt,
16038
15082
  workingDir: this.workingDir,
16039
- messages: this.messages,
16040
- committedMessages: this.committedMessages,
16041
- structuredMessages: this.structuredMessages,
16042
- messageCount: this.committedMessages.length,
15083
+ messages: [],
15084
+ messageCount: 0,
16043
15085
  screenText: screenText.slice(-4e3),
16044
15086
  currentTurnScope: this.currentTurnScope,
16045
15087
  startupBuffer: this.startupBuffer.slice(-4e3),
@@ -16091,7 +15133,7 @@ var init_provider_cli_adapter = __esm({
16091
15133
  lifecycleStatus: this.isWaitingForResponse ? "awaiting_response" : "idle",
16092
15134
  activeModal: this.activeModal,
16093
15135
  currentTurnScope: this.currentTurnScope,
16094
- messages: summarizeCliTraceMessages(this.committedMessages, 5)
15136
+ messages: []
16095
15137
  };
16096
15138
  }
16097
15139
  getProviderResolutionMeta() {
@@ -16384,17 +15426,11 @@ var init_cli_provider_instance = __esm({
16384
15426
  }
16385
15427
  const runtime = this.adapter.getRuntimeMetadata();
16386
15428
  this.maybeAppendRuntimeRecoveryMessage(runtime);
16387
- let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : parseErrorMessage ? normalizeChatMessages(Array.isArray(adapterStatus.messages) ? adapterStatus.messages : []) : [];
15429
+ let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
16388
15430
  const historyMessageCount = Number.isFinite(parsedStatus?.historyMessageCount) ? Math.max(0, Number(parsedStatus.historyMessageCount)) : null;
16389
15431
  if (historyMessageCount !== null) {
16390
15432
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
16391
15433
  }
16392
- const committedMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
16393
- const isActiveNonIdle = adapterStatus.status !== "idle";
16394
- const shouldApplyCommittedFloor = parsedMessages.length < committedMessages.length && (adapterStatus.status === "waiting_approval" || isActiveNonIdle && historyMessageCount === null);
16395
- if (shouldApplyCommittedFloor) {
16396
- parsedMessages = normalizeChatMessages(committedMessages);
16397
- }
16398
15434
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
16399
15435
  const canonicalBackedHistory = this.syncCanonicalSavedHistoryIfNeeded();
16400
15436
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
@@ -16487,11 +15523,9 @@ var init_cli_provider_instance = __esm({
16487
15523
  const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
16488
15524
  const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
16489
15525
  const runtime = this.adapter.getRuntimeMetadata();
16490
- const lastCommittedMessageActivityAt = typeof this.adapter.getLastCommittedMessageActivityAt === "function" ? this.adapter.getLastCommittedMessageActivityAt() : 0;
16491
15526
  return {
16492
15527
  id: this.instanceId,
16493
15528
  status: visibleStatus,
16494
- lastMessageAt: lastCommittedMessageActivityAt || void 0,
16495
15529
  runtimeLifecycle: runtime?.lifecycle ?? null,
16496
15530
  runtimeSurfaceKind: runtime?.surfaceKind,
16497
15531
  runtimeRestoredFromStorage: runtime?.restoredFromStorage === true,
@@ -16597,7 +15631,7 @@ var init_cli_provider_instance = __esm({
16597
15631
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
16598
15632
  const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
16599
15633
  const partial2 = this.adapter.getPartialResponse();
16600
- const progressFingerprint = newStatus === "generating" ? `${partial2 || ""}::${adapterStatus.messages.at(-1)?.content || ""}`.slice(-2e3) : void 0;
15634
+ const progressFingerprint = newStatus === "generating" ? `${partial2 || ""}`.slice(-2e3) : void 0;
16601
15635
  const previousStatus = this.lastStatus;
16602
15636
  if (newStatus !== this.lastStatus) {
16603
15637
  LOG.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
@@ -17043,18 +16077,6 @@ ${effect.notification.body || ""}`.trim();
17043
16077
  receivedAt: message.receivedAt
17044
16078
  }));
17045
16079
  this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
17046
- if (restoredHistory.messages.length > 0) {
17047
- this.adapter.seedCommittedMessages(
17048
- restoredHistory.messages.map((message) => ({
17049
- role: message.role,
17050
- content: message.content,
17051
- timestamp: message.receivedAt,
17052
- receivedAt: message.receivedAt,
17053
- kind: message.kind,
17054
- senderName: message.senderName
17055
- }))
17056
- );
17057
- }
17058
16080
  }
17059
16081
  getProbeDirectories() {
17060
16082
  const dirs = /* @__PURE__ */ new Set();
@@ -39282,13 +38304,24 @@ async function launchWithCdp(options = {}) {
39282
38304
  break;
39283
38305
  }
39284
38306
  }
38307
+ if (!cdpReady) {
38308
+ return {
38309
+ success: false,
38310
+ ideId: targetIde.id,
38311
+ ideName: targetIde.displayName,
38312
+ port,
38313
+ action: "failed",
38314
+ message: "",
38315
+ error: `${targetIde.displayName} launched but CDP did not become available on port ${port}`
38316
+ };
38317
+ }
39285
38318
  return {
39286
38319
  success: true,
39287
38320
  ideId: targetIde.id,
39288
38321
  ideName: targetIde.displayName,
39289
38322
  port,
39290
38323
  action: alreadyRunning ? "restarted" : "started",
39291
- message: cdpReady ? `${targetIde.displayName} launched with CDP on port ${port}` : `${targetIde.displayName} launched (CDP may take a moment to initialize)`
38324
+ message: `${targetIde.displayName} launched with CDP on port ${port}`
39292
38325
  };
39293
38326
  } catch (e) {
39294
38327
  return {
@@ -41285,9 +40318,6 @@ var init_ipc_protocol = __esm({
41285
40318
  });
41286
40319
 
41287
40320
  // ../../oss/packages/daemon-core/src/chat/subscription-updates.ts
41288
- function normalizeSyncMode(syncMode) {
41289
- return syncMode === "append" || syncMode === "replace_tail" || syncMode === "noop" || syncMode === "full" ? syncMode : "full";
41290
- }
41291
40321
  function normalizeModalButtons(value) {
41292
40322
  return Array.isArray(value) ? value.filter((button) => typeof button === "string") : [];
41293
40323
  }
@@ -41314,55 +40344,39 @@ function normalizeSessionModalFields(activeModal) {
41314
40344
  modalButtons: normalizeModalButtons(activeModal.buttons)
41315
40345
  };
41316
40346
  }
41317
- function buildNextChatCursor(cursor, result) {
41318
- return {
41319
- knownMessageCount: Math.max(0, Number(result.totalMessages || cursor.knownMessageCount)),
41320
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : cursor.lastMessageSignature,
41321
- tailLimit: cursor.tailLimit
41322
- };
41323
- }
41324
40347
  function prepareSessionChatTailUpdate(input) {
41325
40348
  const result = input.result;
41326
- if (!result?.success || result.syncMode === "noop") {
40349
+ if (!result?.success) {
41327
40350
  return {
41328
- cursor: result?.success ? buildNextChatCursor(input.cursor, result) : input.cursor,
40351
+ cursor: input.cursor,
41329
40352
  seq: input.seq,
41330
40353
  lastDeliveredSignature: input.lastDeliveredSignature,
41331
40354
  update: null
41332
40355
  };
41333
40356
  }
41334
- const syncMode = normalizeSyncMode(result.syncMode);
41335
- const cursor = {
41336
- knownMessageCount: Math.max(0, Number(result.totalMessages || 0)),
41337
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : "",
41338
- tailLimit: input.cursor.tailLimit
41339
- };
40357
+ const messages = Array.isArray(result.messages) ? result.messages : [];
41340
40358
  const title = typeof result.title === "string" ? result.title : void 0;
41341
40359
  const activeModal = normalizeChatTailActiveModal(result.activeModal);
41342
40360
  const status = typeof result.status === "string" ? result.status : "idle";
41343
40361
  const deliverySignature = buildChatTailDeliverySignature({
41344
40362
  sessionId: input.sessionId,
41345
40363
  ...input.historySessionId ? { historySessionId: input.historySessionId } : {},
41346
- messages: Array.isArray(result.messages) ? result.messages : [],
40364
+ messages,
41347
40365
  status,
41348
40366
  ...title ? { title } : {},
41349
- ...activeModal ? { activeModal } : {},
41350
- syncMode,
41351
- replaceFrom: Number(result.replaceFrom || 0),
41352
- totalMessages: Number(result.totalMessages || 0),
41353
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
40367
+ ...activeModal ? { activeModal } : {}
41354
40368
  });
41355
40369
  const seq = input.seq + 1;
41356
40370
  if (deliverySignature === input.lastDeliveredSignature) {
41357
40371
  return {
41358
- cursor,
40372
+ cursor: input.cursor,
41359
40373
  seq,
41360
40374
  lastDeliveredSignature: input.lastDeliveredSignature,
41361
40375
  update: null
41362
40376
  };
41363
40377
  }
41364
40378
  return {
41365
- cursor,
40379
+ cursor: input.cursor,
41366
40380
  seq,
41367
40381
  lastDeliveredSignature: deliverySignature,
41368
40382
  update: {
@@ -41373,14 +40387,10 @@ function prepareSessionChatTailUpdate(input) {
41373
40387
  ...input.interactionId ? { interactionId: input.interactionId } : {},
41374
40388
  seq,
41375
40389
  timestamp: input.timestamp,
41376
- messages: Array.isArray(result.messages) ? result.messages : [],
40390
+ messages,
41377
40391
  status,
41378
40392
  ...title ? { title } : {},
41379
- ...activeModal ? { activeModal } : {},
41380
- syncMode,
41381
- replaceFrom: Number(result.replaceFrom || 0),
41382
- totalMessages: Number(result.totalMessages || 0),
41383
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
40393
+ ...activeModal ? { activeModal } : {}
41384
40394
  }
41385
40395
  };
41386
40396
  }
@@ -46118,7 +45128,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
46118
45128
  lines.push("Provider category: `cli`");
46119
45129
  lines.push("");
46120
45130
  const funcToFile = {
46121
- parseOutput: "parse_output.js",
45131
+ parseSession: "parse_session.js",
46122
45132
  detectStatus: "detect_status.js",
46123
45133
  parseApproval: "parse_approval.js"
46124
45134
  };
@@ -46207,7 +45217,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
46207
45217
  lines.push("");
46208
45218
  lines.push("| Function | Input | Return |");
46209
45219
  lines.push("|---|---|---|");
46210
- lines.push("| `parseOutput` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |");
45220
+ lines.push("| `parseSession` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |");
46211
45221
  lines.push("| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |");
46212
45222
  lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
46213
45223
  lines.push("");
@@ -46427,7 +45437,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
46427
45437
  lines.push("");
46428
45438
  lines.push("## Required Validation");
46429
45439
  lines.push("1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.");
46430
- lines.push("2. Confirm `parseOutput` produces a stable transcript without duplicating past turns when the PTY redraws.");
45440
+ lines.push("2. Confirm `parseSession` produces a stable transcript without duplicating past turns when the PTY redraws.");
46431
45441
  lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
46432
45442
  lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
46433
45443
  lines.push("5. Confirm the Python file was actually created and executed, not just described in chat text.");
@@ -47726,7 +46736,7 @@ var init_dev_server = __esm({
47726
46736
  lines.push("Provider category: `cli`");
47727
46737
  lines.push("");
47728
46738
  const funcToFile = {
47729
- parseOutput: "parse_output.js",
46739
+ parseSession: "parse_session.js",
47730
46740
  detectStatus: "detect_status.js",
47731
46741
  parseApproval: "parse_approval.js"
47732
46742
  };
@@ -47815,7 +46825,7 @@ var init_dev_server = __esm({
47815
46825
  lines.push("");
47816
46826
  lines.push("| Function | Input | Return |");
47817
46827
  lines.push("|---|---|---|");
47818
- lines.push("| `parseOutput` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |");
46828
+ lines.push("| `parseSession` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |");
47819
46829
  lines.push("| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |");
47820
46830
  lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
47821
46831
  lines.push("");
@@ -47910,7 +46920,7 @@ var init_dev_server = __esm({
47910
46920
  lines.push("");
47911
46921
  lines.push("## Required Validation");
47912
46922
  lines.push("1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.");
47913
- lines.push("2. Confirm `parseOutput` produces a stable transcript without duplicating past turns when the PTY redraws.");
46923
+ lines.push("2. Confirm `parseSession` produces a stable transcript without duplicating past turns when the PTY redraws.");
47914
46924
  lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
47915
46925
  lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
47916
46926
  lines.push("5. Confirm the Python file was actually created and executed, not just described in chat text.");
@@ -50023,8 +49033,6 @@ function handleSubscribe(peerId, msg, peers, handlers) {
50023
49033
  params,
50024
49034
  seq: 0,
50025
49035
  cursor: {
50026
- knownMessageCount: Math.max(0, Number(params.knownMessageCount || 0)),
50027
- lastMessageSignature: typeof params.lastMessageSignature === "string" ? params.lastMessageSignature : "",
50028
49036
  tailLimit: Math.max(0, Number(params.tailLimit || 0))
50029
49037
  },
50030
49038
  lastDeliveredSignature: ""
@@ -51064,12 +50072,8 @@ ${e?.stack || ""}`);
51064
50072
  sessionId: subscription.params.targetSessionId,
51065
50073
  seq: subscription.seq,
51066
50074
  timestamp: Date.now(),
51067
- syncMode: "noop",
51068
50075
  messages: [],
51069
50076
  status: "",
51070
- replaceFrom: 0,
51071
- totalMessages: 0,
51072
- lastMessageSignature: "",
51073
50077
  error: error48?.message || "chat_tail build failed"
51074
50078
  };
51075
50079
  this.screenshotSender.sendTopicUpdateToPeer(peer, errorUpdate);
@@ -59246,7 +58250,7 @@ var init_adhdev_daemon = __esm({
59246
58250
  init_version();
59247
58251
  init_src();
59248
58252
  init_runtime_defaults();
59249
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.63" });
58253
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.65" });
59250
58254
  AdhdevDaemon = class _AdhdevDaemon {
59251
58255
  localHttpServer = null;
59252
58256
  localWss = null;
@@ -59406,8 +58410,6 @@ var init_adhdev_daemon = __esm({
59406
58410
  const result = await this.components.router.execute("read_chat", {
59407
58411
  targetSessionId: subscription.params.targetSessionId,
59408
58412
  ...subscription.params.historySessionId ? { historySessionId: subscription.params.historySessionId } : {},
59409
- knownMessageCount: subscription.cursor.knownMessageCount,
59410
- lastMessageSignature: subscription.cursor.lastMessageSignature,
59411
58413
  ...subscription.cursor.tailLimit > 0 ? { tailLimit: subscription.cursor.tailLimit } : {}
59412
58414
  }, "p2p");
59413
58415
  const interactionId = this.getSessionInteractionId(subscription.params.targetSessionId);
@@ -59435,9 +58437,7 @@ var init_adhdev_daemon = __esm({
59435
58437
  level: "info",
59436
58438
  sessionId: subscription.params.targetSessionId,
59437
58439
  payload: {
59438
- syncMode: prepared.update.syncMode,
59439
- totalMessages: prepared.update.totalMessages,
59440
- replaceFrom: prepared.update.replaceFrom,
58440
+ returnedMessages: prepared.update.messages.length,
59441
58441
  hasModal: !!prepared.update.activeModal,
59442
58442
  hasTitle: typeof prepared.update.title === "string"
59443
58443
  }