adhdev 0.9.64 → 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,127 +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 isReadChatConversationAnchorMessage(message) {
8893
- if (!message) return false;
8894
- const role = String(message.role || "").trim().toLowerCase();
8895
- if (role !== "user" && role !== "assistant") return false;
8896
- const kind = String(message.kind || "standard").trim().toLowerCase();
8897
- return !kind || kind === "standard";
8898
- }
8899
- function buildVisibleReadChatTailMessages(messages, tailLimit) {
8900
- const totalMessages = messages.length;
8901
- if (tailLimit <= 0 || totalMessages <= tailLimit) return messages;
8902
- const tailMessages = messages.slice(-tailLimit);
8903
- if (tailMessages.some(isReadChatConversationAnchorMessage)) return tailMessages;
8904
- const hiddenMessages = messages.slice(0, totalMessages - tailLimit);
8905
- const anchors = [];
8906
- const seenRoles = /* @__PURE__ */ new Set();
8907
- for (let index = hiddenMessages.length - 1; index >= 0 && anchors.length < 2; index -= 1) {
8908
- const message = hiddenMessages[index];
8909
- if (!isReadChatConversationAnchorMessage(message)) continue;
8910
- const role = String(message.role || "").trim().toLowerCase();
8911
- if (seenRoles.has(role)) continue;
8912
- seenRoles.add(role);
8913
- anchors.unshift(message);
8914
- }
8915
- return anchors.length > 0 ? [...anchors, ...tailMessages] : tailMessages;
8916
- }
8917
- function buildBoundedTailSync(messages, cursor) {
8793
+ function buildFullTail(messages, tailLimit) {
8918
8794
  const totalMessages = messages.length;
8919
- const tailMessages = buildVisibleReadChatTailMessages(messages, cursor.tailLimit);
8795
+ const tailMessages = tailLimit > 0 ? messages.slice(-tailLimit) : messages;
8920
8796
  return {
8921
- syncMode: "full",
8922
- replaceFrom: 0,
8923
8797
  messages: tailMessages,
8924
- totalMessages,
8925
- lastMessageSignature: getChatMessageSignature(messages[totalMessages - 1])
8926
- };
8927
- }
8928
- function computeReadChatSync(messages, cursor) {
8929
- const totalMessages = messages.length;
8930
- const lastMessageSignature = getChatMessageSignature(messages[totalMessages - 1]);
8931
- const { knownMessageCount, lastMessageSignature: knownSignature } = cursor;
8932
- if (!knownMessageCount || !knownSignature) {
8933
- return {
8934
- syncMode: "full",
8935
- replaceFrom: 0,
8936
- messages,
8937
- totalMessages,
8938
- lastMessageSignature
8939
- };
8940
- }
8941
- if (knownMessageCount > totalMessages) {
8942
- return {
8943
- syncMode: "full",
8944
- replaceFrom: 0,
8945
- messages,
8946
- totalMessages,
8947
- lastMessageSignature
8948
- };
8949
- }
8950
- if (knownMessageCount === totalMessages && knownSignature === lastMessageSignature) {
8951
- return {
8952
- syncMode: "noop",
8953
- replaceFrom: totalMessages,
8954
- messages: [],
8955
- totalMessages,
8956
- lastMessageSignature
8957
- };
8958
- }
8959
- if (cursor.tailLimit > 0 && knownSignature === lastMessageSignature) {
8960
- const requestedTailCount = Math.min(totalMessages, cursor.tailLimit);
8961
- if (knownMessageCount >= requestedTailCount) {
8962
- return {
8963
- syncMode: "noop",
8964
- replaceFrom: totalMessages,
8965
- messages: [],
8966
- totalMessages,
8967
- lastMessageSignature
8968
- };
8969
- }
8970
- return buildBoundedTailSync(messages, cursor);
8971
- }
8972
- if (knownMessageCount < totalMessages) {
8973
- const anchorSignature = getChatMessageSignature(messages[knownMessageCount - 1]);
8974
- if (anchorSignature === knownSignature) {
8975
- return {
8976
- syncMode: "append",
8977
- replaceFrom: knownMessageCount,
8978
- messages: messages.slice(knownMessageCount),
8979
- totalMessages,
8980
- lastMessageSignature
8981
- };
8982
- }
8983
- if (cursor.tailLimit > 0) {
8984
- const signatureIndex = findLastMessageIndexBySignature(messages, knownSignature);
8985
- if (signatureIndex >= 0) {
8986
- return {
8987
- syncMode: "append",
8988
- replaceFrom: knownMessageCount,
8989
- messages: messages.slice(signatureIndex + 1),
8990
- totalMessages,
8991
- lastMessageSignature
8992
- };
8993
- }
8994
- return buildBoundedTailSync(messages, cursor);
8995
- }
8996
- }
8997
- const replaceFrom = Math.max(0, Math.min(knownMessageCount - 1, totalMessages));
8998
- return {
8999
- syncMode: replaceFrom === 0 ? "full" : "replace_tail",
9000
- replaceFrom,
9001
- messages: replaceFrom === 0 ? messages : messages.slice(replaceFrom),
9002
- totalMessages,
9003
- lastMessageSignature
8798
+ totalMessages
9004
8799
  };
9005
8800
  }
9006
8801
  function hasNonEmptyModalButtons(activeModal) {
@@ -9035,31 +8830,13 @@ function buildReadChatCommandResult(payload, args) {
9035
8830
  } catch (error48) {
9036
8831
  return { success: false, error: error48?.message || String(error48) };
9037
8832
  }
9038
- const messages = collapseReplayDuplicatesFromReadChat(normalizeReadChatMessages(validatedPayload));
9039
- const cursor = normalizeReadChatCursor(args);
9040
- if (!cursor.knownMessageCount && !cursor.lastMessageSignature && cursor.tailLimit > 0 && messages.length > cursor.tailLimit) {
9041
- const tailMessages = buildVisibleReadChatTailMessages(messages, cursor.tailLimit);
9042
- const lastMessageSignature = getChatMessageSignature(messages[messages.length - 1]);
9043
- return {
9044
- success: true,
9045
- ...validatedPayload,
9046
- messages: tailMessages,
9047
- syncMode: "full",
9048
- replaceFrom: 0,
9049
- totalMessages: messages.length,
9050
- lastMessageSignature,
9051
- ...debugReadChat ? { debugReadChat } : {}
9052
- };
9053
- }
9054
- const sync = computeReadChatSync(messages, cursor);
8833
+ const messages = normalizeReadChatMessages(validatedPayload);
8834
+ const sync = buildFullTail(messages, normalizeReadChatTailLimit(args));
9055
8835
  return {
9056
8836
  success: true,
9057
8837
  ...validatedPayload,
9058
8838
  messages: sync.messages,
9059
- syncMode: sync.syncMode,
9060
- replaceFrom: sync.replaceFrom,
9061
8839
  totalMessages: sync.totalMessages,
9062
- lastMessageSignature: sync.lastMessageSignature,
9063
8840
  ...debugReadChat ? { debugReadChat } : {}
9064
8841
  };
9065
8842
  }
@@ -9277,10 +9054,6 @@ async function handleGetChatDebugBundle(h, args) {
9277
9054
  status: readResult.status,
9278
9055
  title: readResult.title,
9279
9056
  totalMessages: readResult.totalMessages,
9280
- returnedMessages: Array.isArray(readResult.messages) ? readResult.messages.length : void 0,
9281
- syncMode: readResult.syncMode,
9282
- replaceFrom: readResult.replaceFrom,
9283
- lastMessageSignature: readResult.lastMessageSignature,
9284
9057
  providerSessionId: readResult.providerSessionId,
9285
9058
  transcriptAuthority: readResult.transcriptAuthority,
9286
9059
  coverage: readResult.coverage,
@@ -9390,22 +9163,13 @@ function toNonNegativeNumber(value) {
9390
9163
  return Number.isFinite(numeric) ? Math.max(0, numeric) : 0;
9391
9164
  }
9392
9165
  function getCliVisibleTranscriptCount(adapter) {
9393
- const adapterStatus = adapter?.getStatus?.() || {};
9394
- const adapterMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
9395
- let parsedRecord = null;
9396
- if (typeof adapter?.getScriptParsedStatus === "function") {
9397
- try {
9398
- const parsed = parseMaybeJson(adapter.getScriptParsedStatus());
9399
- parsedRecord = parsed && typeof parsed === "object" ? parsed : null;
9400
- } catch {
9401
- parsedRecord = null;
9402
- }
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;
9403
9172
  }
9404
- const parsedMessages = Array.isArray(parsedRecord?.messages) ? parsedRecord.messages : [];
9405
- if (!parsedRecord) return adapterMessages.length;
9406
- const parsedIsProviderAuthoritative = parsedRecord.transcriptAuthority === "provider" || parsedRecord.coverage === "full";
9407
- const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && adapterMessages.length > 0 && adapterMessages.length > parsedMessages.length;
9408
- return shouldPreferAdapterMessages ? adapterMessages.length : parsedMessages.length;
9409
9173
  }
9410
9174
  async function getStableExtensionBaseline(h) {
9411
9175
  const first = await readExtensionChatState(h);
@@ -9467,52 +9231,46 @@ async function handleReadChat(h, args) {
9467
9231
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
9468
9232
  if (adapter) {
9469
9233
  _log(`${transport} adapter: ${adapter.cliType}`);
9234
+ if (typeof adapter.getScriptParsedStatus !== "function") {
9235
+ return { success: false, error: `${transport} adapter parseSession unavailable` };
9236
+ }
9470
9237
  let parsedStatus = null;
9471
- if (typeof adapter.getScriptParsedStatus === "function") {
9472
- try {
9473
- parsedStatus = parseMaybeJson(adapter.getScriptParsedStatus());
9474
- } catch (error48) {
9475
- return { success: false, error: error48?.message || String(error48) };
9476
- }
9238
+ try {
9239
+ parsedStatus = parseMaybeJson(adapter.getScriptParsedStatus());
9240
+ } catch (error48) {
9241
+ return { success: false, error: error48?.message || String(error48) };
9477
9242
  }
9478
9243
  const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
9479
- const adapterStatus = adapter.getStatus();
9480
- const parsedIsProviderAuthoritative = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.coverage === "full";
9481
- const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
9482
- const parsedShowsApproval = hasNonEmptyModalButtons(parsedRecord?.activeModal) && parsedRecord?.status === "waiting_approval";
9483
- const status = parsedRecord ? {
9484
- ...parsedRecord,
9485
- messages: shouldPreferAdapterMessages ? adapterStatus.messages : parsedRecord.messages,
9486
- status: parsedShowsApproval ? parsedRecord.status : adapterStatus.status !== "idle" ? adapterStatus.status : parsedRecord.status || adapterStatus.status,
9487
- activeModal: parsedRecord.activeModal || adapterStatus.activeModal
9488
- } : adapterStatus;
9489
- const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
9490
- const providerSessionId = typeof parsedRecord?.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
9491
- const transcriptAuthority = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
9492
- const coverage = parsedRecord?.coverage === "full" || parsedRecord?.coverage === "tail" || parsedRecord?.coverage === "current-turn" ? parsedRecord.coverage : void 0;
9493
- if (status) {
9494
- 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}`);
9495
- return buildReadChatCommandResult({
9496
- messages: status.messages || [],
9497
- status: status.status,
9498
- activeModal: status.activeModal,
9499
- debugReadChat: {
9500
- provider: adapter.cliType,
9501
- targetSessionId: String(args?.targetSessionId || ""),
9502
- adapterStatus: String(adapterStatus.status || ""),
9503
- parsedStatus: String(parsedRecord?.status || ""),
9504
- returnedStatus: String(status.status || ""),
9505
- shouldPreferAdapterMessages,
9506
- adapterMsgCount: Array.isArray(adapterStatus.messages) ? adapterStatus.messages.length : 0,
9507
- parsedMsgCount: Array.isArray(parsedRecord?.messages) ? parsedRecord.messages.length : 0,
9508
- returnedMsgCount: Array.isArray(status.messages) ? status.messages.length : 0
9509
- },
9510
- ...title ? { title } : {},
9511
- ...providerSessionId ? { providerSessionId } : {},
9512
- ...transcriptAuthority ? { transcriptAuthority } : {},
9513
- ...coverage ? { coverage } : {}
9514
- }, args);
9515
- }
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);
9516
9274
  }
9517
9275
  return { success: false, error: `${transport} adapter not found` };
9518
9276
  }
@@ -10366,7 +10124,6 @@ var init_chat_commands = __esm({
10366
10124
  init_logger();
10367
10125
  init_debug_trace();
10368
10126
  init_chat_signatures();
10369
- init_chat_message_normalization();
10370
10127
  RECENT_SEND_WINDOW_MS = 1200;
10371
10128
  READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25e3;
10372
10129
  recentSendByTarget = /* @__PURE__ */ new Map();
@@ -13106,67 +12863,6 @@ function promptLikelyVisible(screenText, promptSnippet) {
13106
12863
  function normalizeScreenSnapshot(text) {
13107
12864
  return sanitizeTerminalText(String(text || "")).replace(/\s+/g, " ").trim();
13108
12865
  }
13109
- function shouldReflowComparableMessageLines(lines) {
13110
- 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));
13111
- }
13112
- function joinComparableMessageLines(lines) {
13113
- return lines.reduce((acc, line) => {
13114
- const next = String(line || "").trim();
13115
- if (!next) return acc;
13116
- if (!acc) return next;
13117
- if (/[,\d]$/.test(acc) && /^\d/.test(next)) {
13118
- return `${acc}${next}`;
13119
- }
13120
- if (/[A-Za-z]$/.test(acc) && /^\d/.test(next)) {
13121
- return `${acc}${next}`;
13122
- }
13123
- const fragmentMatch = acc.match(/([A-Za-z]{1,4})$/);
13124
- const fragment = fragmentMatch ? fragmentMatch[1].toLowerCase() : "";
13125
- if (/^[a-z]/.test(next) && fragment && !COMMON_COMPARABLE_WRAP_WORDS.has(fragment)) {
13126
- return `${acc}${next}`;
13127
- }
13128
- return `${acc} ${next}`;
13129
- }, "").replace(/\s+([,.;:!?])/g, "$1").replace(/(\d)\s+,/g, "$1,").replace(/\s+/g, " ").trim();
13130
- }
13131
- function normalizeComparableMessageContent(text) {
13132
- const lines = String(text || "").split(/\r\n|\n|\r/g).map((line) => line.trim()).filter(Boolean);
13133
- if (lines.length === 0) return "";
13134
- if (shouldReflowComparableMessageLines(lines)) {
13135
- return joinComparableMessageLines(lines);
13136
- }
13137
- return lines.join(" ").replace(/\s+/g, " ").trim();
13138
- }
13139
- function trimPromptEchoPrefix(text, promptText) {
13140
- const prompt2 = normalizeComparableMessageContent(String(promptText || ""));
13141
- if (!prompt2) return String(text || "");
13142
- const lines = String(text || "").split(/\r\n|\n|\r/g);
13143
- let dropCount = 0;
13144
- for (let index = 0; index < Math.min(lines.length, 6); index += 1) {
13145
- const fragment = normalizeComparableMessageContent(lines[index].replace(/^[.…]+\s*/, ""));
13146
- if (!fragment) {
13147
- if (dropCount === index) dropCount = index + 1;
13148
- continue;
13149
- }
13150
- const fragmentWordCount = fragment ? fragment.split(/\s+/).filter(Boolean).length : 0;
13151
- const canBePromptEcho = fragment.length >= 16 || fragmentWordCount >= 4;
13152
- if (canBePromptEcho && prompt2.includes(fragment)) {
13153
- dropCount = index + 1;
13154
- continue;
13155
- }
13156
- break;
13157
- }
13158
- return lines.slice(dropCount).join("\n").trim();
13159
- }
13160
- function getLastUserPromptText(messages) {
13161
- const items = Array.isArray(messages) ? messages : [];
13162
- for (let index = items.length - 1; index >= 0; index -= 1) {
13163
- const message = items[index];
13164
- if (message?.role === "user" && typeof message.content === "string" && message.content.trim()) {
13165
- return message.content;
13166
- }
13167
- }
13168
- return "";
13169
- }
13170
12866
  function parsePatternEntry(x) {
13171
12867
  if (x instanceof RegExp) return x;
13172
12868
  if (x && typeof x === "object" && typeof x.source === "string") {
@@ -13193,7 +12889,7 @@ function normalizeCliProviderForRuntime(raw) {
13193
12889
  }
13194
12890
  };
13195
12891
  }
13196
- var os11, path13, import_child_process4, buildCliSpawnEnv, COMMON_COMPARABLE_WRAP_WORDS;
12892
+ var os11, path13, import_child_process4, buildCliSpawnEnv;
13197
12893
  var init_provider_cli_shared = __esm({
13198
12894
  "../../oss/packages/daemon-core/src/cli-adapters/provider-cli-shared.ts"() {
13199
12895
  "use strict";
@@ -13202,32 +12898,6 @@ var init_provider_cli_shared = __esm({
13202
12898
  import_child_process4 = require("child_process");
13203
12899
  init_spawn_env();
13204
12900
  buildCliSpawnEnv = sanitizeSpawnEnv;
13205
- COMMON_COMPARABLE_WRAP_WORDS = /* @__PURE__ */ new Set([
13206
- "a",
13207
- "an",
13208
- "and",
13209
- "as",
13210
- "at",
13211
- "but",
13212
- "by",
13213
- "for",
13214
- "from",
13215
- "in",
13216
- "into",
13217
- "is",
13218
- "it",
13219
- "of",
13220
- "on",
13221
- "or",
13222
- "that",
13223
- "the",
13224
- "their",
13225
- "then",
13226
- "this",
13227
- "to",
13228
- "was",
13229
- "with"
13230
- ]);
13231
12901
  }
13232
12902
  });
13233
12903
 
@@ -13238,169 +12908,8 @@ function sliceFromOffset(text, start) {
13238
12908
  if (start >= text.length) return "";
13239
12909
  return text.slice(start);
13240
12910
  }
13241
- function hydrateCliParsedMessages(parsedMessages, options) {
13242
- const { committedMessages, scope, lastOutputAt } = options;
13243
- const referenceMessages = [...committedMessages];
13244
- const referenceComparables = new Array(referenceMessages.length);
13245
- const usedReferenceIndexes = /* @__PURE__ */ new Set();
13246
- const now = options.now ?? Date.now();
13247
- let exactReferenceIndexesByKey = null;
13248
- const exactReferenceCursorByKey = /* @__PURE__ */ new Map();
13249
- const hasFiniteTimestamp = (message) => typeof message?.timestamp === "number" && Number.isFinite(message.timestamp);
13250
- const getReferenceComparable = (index) => {
13251
- if (typeof referenceComparables[index] === "string") return referenceComparables[index] || "";
13252
- const comparable = normalizeComparableMessageContent(referenceMessages[index]?.content || "");
13253
- referenceComparables[index] = comparable;
13254
- return comparable;
13255
- };
13256
- const messagesShareStableIdentity = (parsed, reference) => {
13257
- if (!parsed || !reference) return false;
13258
- const parsedId = typeof parsed.id === "string" ? parsed.id.trim() : "";
13259
- const referenceId = typeof reference.id === "string" ? reference.id.trim() : "";
13260
- if (parsedId && referenceId && parsedId === referenceId) return true;
13261
- return typeof parsed.index === "number" && Number.isFinite(parsed.index) && typeof reference.index === "number" && Number.isFinite(reference.index) && parsed.index === reference.index;
13262
- };
13263
- const exactReferenceKey = (role, comparable) => `${role}\0${comparable}`;
13264
- const ensureExactReferenceIndex = () => {
13265
- if (exactReferenceIndexesByKey) return exactReferenceIndexesByKey;
13266
- const byKey = /* @__PURE__ */ new Map();
13267
- for (let i = 0; i < referenceMessages.length; i++) {
13268
- const candidate = referenceMessages[i];
13269
- if (!candidate || candidate.role !== "user" && candidate.role !== "assistant" || !hasFiniteTimestamp(candidate)) continue;
13270
- const comparable = getReferenceComparable(i);
13271
- if (!comparable) continue;
13272
- const key = exactReferenceKey(candidate.role, comparable);
13273
- const indexes = byKey.get(key);
13274
- if (indexes) {
13275
- indexes.push(i);
13276
- } else {
13277
- byKey.set(key, [i]);
13278
- }
13279
- }
13280
- exactReferenceIndexesByKey = byKey;
13281
- return byKey;
13282
- };
13283
- const takeExactReferenceTimestamp = (role, normalizedContent) => {
13284
- const key = exactReferenceKey(role, normalizedContent);
13285
- const indexes = ensureExactReferenceIndex().get(key);
13286
- if (!indexes) return void 0;
13287
- let cursor = exactReferenceCursorByKey.get(key) || 0;
13288
- while (cursor < indexes.length) {
13289
- const candidateIndex = indexes[cursor];
13290
- cursor += 1;
13291
- if (usedReferenceIndexes.has(candidateIndex)) continue;
13292
- const candidate = referenceMessages[candidateIndex];
13293
- if (!candidate || candidate.role !== role || !hasFiniteTimestamp(candidate)) continue;
13294
- usedReferenceIndexes.add(candidateIndex);
13295
- exactReferenceCursorByKey.set(key, cursor);
13296
- return candidate.timestamp;
13297
- }
13298
- exactReferenceCursorByKey.set(key, cursor);
13299
- return void 0;
13300
- };
13301
- const findReferenceTimestamp = (message, role, content, parsedIndex) => {
13302
- const sameIndex = referenceMessages[parsedIndex];
13303
- if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && hasFiniteTimestamp(sameIndex) && messagesShareStableIdentity(message, sameIndex)) {
13304
- usedReferenceIndexes.add(parsedIndex);
13305
- return sameIndex.timestamp;
13306
- }
13307
- const normalizedContent = normalizeComparableMessageContent(content);
13308
- if (!normalizedContent) return void 0;
13309
- if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && getReferenceComparable(parsedIndex) === normalizedContent && hasFiniteTimestamp(sameIndex)) {
13310
- usedReferenceIndexes.add(parsedIndex);
13311
- return sameIndex.timestamp;
13312
- }
13313
- const exactTimestamp = takeExactReferenceTimestamp(role, normalizedContent);
13314
- if (typeof exactTimestamp === "number") return exactTimestamp;
13315
- for (let i = 0; i < referenceMessages.length; i++) {
13316
- if (usedReferenceIndexes.has(i)) continue;
13317
- const candidate = referenceMessages[i];
13318
- if (!candidate || candidate.role !== role) continue;
13319
- const candidateContent = getReferenceComparable(i);
13320
- if (!candidateContent) continue;
13321
- const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
13322
- if (!fuzzyMatch) continue;
13323
- if (hasFiniteTimestamp(candidate)) {
13324
- usedReferenceIndexes.add(i);
13325
- return candidate.timestamp;
13326
- }
13327
- }
13328
- return void 0;
13329
- };
13330
- return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message, index) => {
13331
- const role = message.role;
13332
- const content = typeof message.content === "string" ? message.content : String(message.content || "");
13333
- const parsedTimestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0;
13334
- const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(message, role, content, index);
13335
- const fallbackTimestamp = role === "user" ? scope?.startedAt || now : lastOutputAt || scope?.startedAt || now;
13336
- const timestamp = referenceTimestamp ?? fallbackTimestamp;
13337
- return {
13338
- ...message,
13339
- role,
13340
- content,
13341
- timestamp,
13342
- receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp
13343
- };
13344
- });
13345
- }
13346
- function chooseMoreComparableCliMessage(left2, right2, leftComparable = normalizeComparableMessageContent(left2.content || ""), rightComparable = normalizeComparableMessageContent(right2.content || "")) {
13347
- if (leftComparable && leftComparable === rightComparable) {
13348
- const leftNewlines = String(left2.content || "").split(/\r\n|\n|\r/g).length - 1;
13349
- const rightNewlines = String(right2.content || "").split(/\r\n|\n|\r/g).length - 1;
13350
- return rightNewlines < leftNewlines ? right2 : left2;
13351
- }
13352
- return rightComparable.length > leftComparable.length ? right2 : left2;
13353
- }
13354
- function dedupeConsecutiveComparableCliMessages(messages) {
13355
- const deduped = [];
13356
- for (const message of messages) {
13357
- const current = {
13358
- ...message,
13359
- content: typeof message.content === "string" ? message.content : String(message.content || "")
13360
- };
13361
- const currentComparable = normalizeComparableMessageContent(current.content || "");
13362
- const previous = deduped[deduped.length - 1];
13363
- if (!previous) {
13364
- deduped.push({ message: current, comparable: currentComparable });
13365
- continue;
13366
- }
13367
- const sameRole = previous.message.role === current.role;
13368
- const sameKind = (previous.message.kind || "standard") === (current.kind || "standard");
13369
- const sameSender = (previous.message.senderName || "") === (current.senderName || "");
13370
- const comparableMatch = previous.comparable && previous.comparable === currentComparable;
13371
- if (sameRole && sameKind && sameSender && comparableMatch) {
13372
- const selected = chooseMoreComparableCliMessage(
13373
- previous.message,
13374
- current,
13375
- previous.comparable,
13376
- currentComparable
13377
- );
13378
- deduped[deduped.length - 1] = {
13379
- message: selected,
13380
- comparable: selected === current ? currentComparable : previous.comparable
13381
- };
13382
- continue;
13383
- }
13384
- deduped.push({ message: current, comparable: currentComparable });
13385
- }
13386
- return deduped.map((entry) => entry.message);
13387
- }
13388
- function normalizeCliParsedMessages(parsedMessages, options) {
13389
- return dedupeConsecutiveComparableCliMessages(hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
13390
- role: message.role,
13391
- content: message.content,
13392
- timestamp: message.timestamp,
13393
- receivedAt: message.receivedAt,
13394
- kind: message.kind,
13395
- id: message.id,
13396
- index: message.index,
13397
- providerUnitKey: message.providerUnitKey,
13398
- bubbleId: message.bubbleId,
13399
- bubbleState: message.bubbleState,
13400
- _turnKey: message._turnKey,
13401
- meta: message.meta,
13402
- senderName: message.senderName
13403
- })));
12911
+ function normalizeCliParsedMessages(parsedMessages, _options) {
12912
+ return Array.isArray(parsedMessages) ? parsedMessages : [];
13404
12913
  }
13405
12914
  function buildCliParseInput(options) {
13406
12915
  const {
@@ -13610,40 +13119,8 @@ var provider_cli_adapter_exports = {};
13610
13119
  __export(provider_cli_adapter_exports, {
13611
13120
  ProviderCliAdapter: () => ProviderCliAdapter,
13612
13121
  appendBoundedText: () => appendBoundedText,
13613
- normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime,
13614
- sanitizeCliStandardMessageContent: () => sanitizeCliStandardMessageContent,
13615
- trimLastAssistantEchoForCliMessages: () => trimLastAssistantEchoForCliMessages
13616
- });
13617
- function normalizeComparableTranscriptText(value) {
13618
- return sanitizeTerminalText(String(value || "")).replace(/\s+/g, " ").trim();
13619
- }
13620
- function hasVisibleInterruptPrompt(text) {
13621
- const interruptCopyPattern = /\bEnter\s+to\s+interrupt\b(?:\s*,?\s*Ctrl\s*(?:\+|-)?\s*C\s+to\s+cancel)?/i;
13622
- return sanitizeTerminalText(text || "").split(/\r?\n/g).some((line) => {
13623
- const trimmed = line.trim();
13624
- if (!interruptCopyPattern.test(trimmed)) return false;
13625
- return /^(?:[^A-Za-z0-9\s]{1,8}\s+)?[❯›>]\s+/.test(trimmed);
13626
- });
13627
- }
13628
- function parsedTranscriptIsRicherThanCommitted(parsedMessages, committedMessages) {
13629
- if (!Array.isArray(parsedMessages) || !Array.isArray(committedMessages)) return false;
13630
- if (parsedMessages.length > committedMessages.length) return true;
13631
- if (parsedMessages.length !== committedMessages.length) return false;
13632
- for (let index = 0; index < parsedMessages.length; index += 1) {
13633
- const parsed = parsedMessages[index];
13634
- const committed = committedMessages[index];
13635
- if (!parsed || !committed) return false;
13636
- if ((parsed.role || "") !== (committed.role || "")) return false;
13637
- if (parsed.id && committed.id && String(parsed.id) !== String(committed.id)) return false;
13638
- if (typeof parsed.index === "number" && typeof committed.index === "number" && parsed.index !== committed.index) return false;
13639
- const parsedText = normalizeComparableTranscriptText(parsed.content);
13640
- const committedText = normalizeComparableTranscriptText(committed.content);
13641
- if (!parsedText || !committedText || parsedText === committedText) continue;
13642
- if (parsedText.length > committedText.length && parsedText.startsWith(committedText)) return true;
13643
- return false;
13644
- }
13645
- return false;
13646
- }
13122
+ normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
13123
+ });
13647
13124
  function appendBoundedText(current, chunk, maxChars) {
13648
13125
  if (!chunk) return current.length <= maxChars ? current : current.slice(-maxChars);
13649
13126
  if (maxChars <= 0) return "";
@@ -13652,76 +13129,7 @@ function appendBoundedText(current, chunk, maxChars) {
13652
13129
  if (current.length <= keepFromCurrent) return current + chunk;
13653
13130
  return current.slice(-keepFromCurrent) + chunk;
13654
13131
  }
13655
- function isLikelyCommittedActivityPrefixContinuation(line) {
13656
- const trimmed = String(line || "").trim();
13657
- if (!trimmed) return false;
13658
- if (COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(trimmed)) return false;
13659
- if (/\s/.test(trimmed)) return false;
13660
- if (/[가-힣]/.test(trimmed)) return false;
13661
- if (trimmed.length > 96) return false;
13662
- return /^[A-Za-z0-9_./:@+%=-]+$/.test(trimmed);
13663
- }
13664
- function parseCommittedActivityPrefixBlock(lines, index) {
13665
- const first = String(lines[index] || "").trim();
13666
- if (!COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(first)) return null;
13667
- const parts = [first];
13668
- let nextIndex = index + 1;
13669
- while (nextIndex < lines.length && isLikelyCommittedActivityPrefixContinuation(lines[nextIndex])) {
13670
- parts.push(String(lines[nextIndex] || "").trim());
13671
- nextIndex += 1;
13672
- }
13673
- return { label: parts.join(""), nextIndex };
13674
- }
13675
- function sanitizeCliStandardMessageContent(content) {
13676
- const source = String(content || "").trim();
13677
- if (!source) return "";
13678
- const lines = source.split(/\r?\n/);
13679
- if (lines.length < 4) return source;
13680
- const counts = /* @__PURE__ */ new Map();
13681
- for (let index = 0; index < lines.length; index += 1) {
13682
- const block = parseCommittedActivityPrefixBlock(lines, index);
13683
- if (!block) continue;
13684
- counts.set(block.label, (counts.get(block.label) || 0) + 1);
13685
- index = block.nextIndex - 1;
13686
- }
13687
- const repeatedLabels = new Set(
13688
- Array.from(counts.entries()).filter(([, count]) => count >= 3).map(([label]) => label)
13689
- );
13690
- if (repeatedLabels.size === 0) return source;
13691
- const stripped = [];
13692
- let removed = 0;
13693
- for (let index = 0; index < lines.length; index += 1) {
13694
- const block = parseCommittedActivityPrefixBlock(lines, index);
13695
- if (block && repeatedLabels.has(block.label)) {
13696
- removed += 1;
13697
- index = block.nextIndex - 1;
13698
- continue;
13699
- }
13700
- stripped.push(lines[index]);
13701
- }
13702
- const next = stripped.join("\n").replace(/\n{3,}/g, "\n\n").trim();
13703
- return removed >= 3 && next.length >= 80 ? next : source;
13704
- }
13705
- function sanitizeCommittedMessageForDisplay(message) {
13706
- if (!message || message.role !== "assistant" || (message.kind || "standard") !== "standard") return message;
13707
- const content = sanitizeCliStandardMessageContent(message.content);
13708
- if (content === message.content) return message;
13709
- return { ...message, content };
13710
- }
13711
- function trimLastAssistantEchoForCliMessages(messages, prompt2) {
13712
- if (!prompt2) return;
13713
- for (let index = messages.length - 1; index >= 0; index -= 1) {
13714
- const message = messages[index];
13715
- if (!message || message.role !== "assistant" || typeof message.content !== "string") continue;
13716
- if ((message.kind || "standard") !== "standard") continue;
13717
- message.content = trimPromptEchoPrefix(message.content, prompt2);
13718
- if (!message.content.trim()) {
13719
- messages.splice(index, 1);
13720
- }
13721
- return;
13722
- }
13723
- }
13724
- var os13, COMMITTED_ACTIVITY_PREFIX_BLOCK_RE, ProviderCliAdapter;
13132
+ var os13, ProviderCliAdapter;
13725
13133
  var init_provider_cli_adapter = __esm({
13726
13134
  "../../oss/packages/daemon-core/src/cli-adapters/provider-cli-adapter.ts"() {
13727
13135
  "use strict";
@@ -13731,13 +13139,10 @@ var init_provider_cli_adapter = __esm({
13731
13139
  init_terminal_screen();
13732
13140
  init_pty_transport();
13733
13141
  init_provider_cli_shared();
13734
- init_chat_message_normalization();
13735
- init_read_chat_contract();
13736
13142
  init_provider_cli_parse();
13737
13143
  init_provider_cli_config();
13738
13144
  init_provider_cli_runtime();
13739
13145
  init_provider_cli_shared();
13740
- COMMITTED_ACTIVITY_PREFIX_BLOCK_RE = /^(?:📖|💻|🔎|📚|📋|✏️|📝|🔧|🛠️|⚙️)\s+(.+)$/;
13741
13146
  ProviderCliAdapter = class _ProviderCliAdapter {
13742
13147
  constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
13743
13148
  this.extraArgs = extraArgs;
@@ -13780,11 +13185,6 @@ var init_provider_cli_adapter = __esm({
13780
13185
  provider;
13781
13186
  ptyProcess = null;
13782
13187
  transportFactory;
13783
- messages = [];
13784
- committedMessages = [];
13785
- structuredMessages = [];
13786
- committedMessagesActivitySignature = "";
13787
- committedMessagesChangedAt = 0;
13788
13188
  currentStatus = "starting";
13789
13189
  onStatusChange = null;
13790
13190
  responseBuffer = "";
@@ -13864,11 +13264,8 @@ var init_provider_cli_adapter = __esm({
13864
13264
  traceSeq = 0;
13865
13265
  traceSessionId = "";
13866
13266
  parsedStatusCache = null;
13867
- lastStatusHotPathParseAt = Number.NEGATIVE_INFINITY;
13868
- static STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS = 1e3;
13869
13267
  static SCREEN_SNAPSHOT_MIN_INTERVAL_MS = 250;
13870
13268
  static MAX_TRACE_ENTRIES = 250;
13871
- static PARSE_MESSAGE_TAIL_LIMIT = 100;
13872
13269
  providerResolutionMeta;
13873
13270
  static FINISH_RETRY_DELAY_MS = 300;
13874
13271
  static MAX_FINISH_RETRIES = 2;
@@ -13889,35 +13286,6 @@ var init_provider_cli_adapter = __esm({
13889
13286
  recordBoundedAppendDrop(previousLength, appendedLength, nextLength) {
13890
13287
  return Math.max(0, previousLength + appendedLength - nextLength);
13891
13288
  }
13892
- buildCommittedMessagesActivitySignature() {
13893
- const last = this.committedMessages[this.committedMessages.length - 1];
13894
- return [
13895
- String(this.committedMessages.length),
13896
- String(last?.role || ""),
13897
- String(last?.kind || ""),
13898
- String(last?.senderName || ""),
13899
- String(last?.timestamp || ""),
13900
- String(last?.receivedAt || ""),
13901
- normalizeComparableMessageContent(last?.content || "").slice(-240)
13902
- ].join("|");
13903
- }
13904
- syncMessageViews() {
13905
- const signature = this.buildCommittedMessagesActivitySignature();
13906
- if (signature !== this.committedMessagesActivitySignature) {
13907
- this.committedMessagesActivitySignature = signature;
13908
- this.committedMessagesChangedAt = Date.now();
13909
- }
13910
- this.messages = [...this.committedMessages];
13911
- this.structuredMessages = [...this.committedMessages];
13912
- }
13913
- getLastCommittedMessageActivityAt() {
13914
- const last = this.committedMessages[this.committedMessages.length - 1];
13915
- const messageTime = Math.max(
13916
- typeof last?.receivedAt === "number" && Number.isFinite(last.receivedAt) ? last.receivedAt : 0,
13917
- typeof last?.timestamp === "number" && Number.isFinite(last.timestamp) ? last.timestamp : 0
13918
- );
13919
- return Math.max(messageTime, this.committedMessagesChangedAt || 0);
13920
- }
13921
13289
  readTerminalScreenText(now = Date.now()) {
13922
13290
  const screenText = this.terminalScreen.getText() || "";
13923
13291
  this.lastScreenText = screenText;
@@ -13937,7 +13305,7 @@ var init_provider_cli_adapter = __esm({
13937
13305
  }
13938
13306
  getFreshParsedStatusCache() {
13939
13307
  const cached2 = this.parsedStatusCache;
13940
- 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) {
13941
13309
  return cached2.result;
13942
13310
  }
13943
13311
  return null;
@@ -13948,45 +13316,6 @@ var init_provider_cli_adapter = __esm({
13948
13316
  shouldUseFullProviderTranscriptContext() {
13949
13317
  return this.providerOwnsTranscript() && this.provider.transcriptContext === "full";
13950
13318
  }
13951
- selectParseBaseMessages(baseMessages) {
13952
- if (this.shouldUseFullProviderTranscriptContext()) return baseMessages;
13953
- if (baseMessages.length <= _ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
13954
- return baseMessages.slice(-_ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
13955
- }
13956
- messagesShareStableIdentity(left2, right2) {
13957
- if (left2 === right2) return true;
13958
- if (!left2 || !right2) return false;
13959
- if ((left2.role || "") !== (right2.role || "")) return false;
13960
- if (left2.id && right2.id && String(left2.id) === String(right2.id)) return true;
13961
- if (typeof left2.index === "number" && typeof right2.index === "number" && left2.index === right2.index) return true;
13962
- return false;
13963
- }
13964
- messagesComparable(left2, right2) {
13965
- if (this.messagesShareStableIdentity(left2, right2)) return true;
13966
- if (!left2 || !right2) return false;
13967
- if ((left2.role || "") !== (right2.role || "")) return false;
13968
- const leftText = normalizeComparableTranscriptText(left2.content);
13969
- const rightText = normalizeComparableTranscriptText(right2.content);
13970
- return !!leftText && leftText === rightText;
13971
- }
13972
- stitchParsedMessagesWithCommittedBase(parsedMessages, fullBaseMessages, parseBaseMessages) {
13973
- if (!Array.isArray(parsedMessages) || parsedMessages.length === 0) return parsedMessages;
13974
- if (fullBaseMessages.length <= parseBaseMessages.length) return parsedMessages;
13975
- const parsedFirst = parsedMessages[0];
13976
- const fullFirst = fullBaseMessages[0];
13977
- if (parsedMessages.length >= fullBaseMessages.length && this.messagesComparable(parsedFirst, fullFirst)) {
13978
- return parsedMessages;
13979
- }
13980
- const tailFirst = parseBaseMessages[0];
13981
- if (tailFirst && this.messagesComparable(parsedFirst, tailFirst)) {
13982
- const prefixLength = fullBaseMessages.length - parseBaseMessages.length;
13983
- const prefix = fullBaseMessages.slice(0, prefixLength);
13984
- const shouldSanitizePrefix = !!this.currentTurnScope || this.currentStatus !== "idle" || !!this.activeModal;
13985
- const nextPrefix = shouldSanitizePrefix ? prefix.map((message) => sanitizeCommittedMessageForDisplay(message)) : prefix;
13986
- return [...nextPrefix, ...parsedMessages];
13987
- }
13988
- return [...fullBaseMessages, ...parsedMessages];
13989
- }
13990
13319
  getIdleFinishConfirmMs() {
13991
13320
  return this.timeouts.idleFinishConfirm;
13992
13321
  }
@@ -14439,9 +13768,6 @@ var init_provider_cli_adapter = __esm({
14439
13768
  `[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(summarizeCliTraceText(finalScreenText, 240)).slice(0, 280)}`
14440
13769
  );
14441
13770
  }
14442
- trimLastAssistantEcho(messages, prompt2) {
14443
- trimLastAssistantEchoForCliMessages(messages, prompt2);
14444
- }
14445
13771
  clearAllTimers() {
14446
13772
  if (this.responseTimeout) {
14447
13773
  clearTimeout(this.responseTimeout);
@@ -14537,10 +13863,10 @@ var init_provider_cli_adapter = __esm({
14537
13863
  }
14538
13864
  const session = this.runParseSession();
14539
13865
  if (!session) return;
14540
- const { status, messages, modal, parsedStatus } = session;
13866
+ const { status, messages, parsedStatus } = session;
13867
+ const modal = session.activeModal ?? session.modal ?? null;
14541
13868
  const parsedMessages = normalizeCliParsedMessages(messages, {
14542
- committedMessages: this.committedMessages,
14543
- scope: this.currentTurnScope,
13869
+ scope: null,
14544
13870
  lastOutputAt: this.lastOutputAt
14545
13871
  });
14546
13872
  if (this.maybeCommitVisibleIdleTranscript(session, parsedMessages)) return;
@@ -14720,7 +14046,7 @@ var init_provider_cli_adapter = __esm({
14720
14046
  const effectiveScreenText = screenText || this.accumulatedBuffer;
14721
14047
  const noActiveTurn = !this.currentTurnScope;
14722
14048
  const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(effectiveScreenText);
14723
- const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant && parsedMessages.length > this.committedMessages.length;
14049
+ const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant;
14724
14050
  if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
14725
14051
  return;
14726
14052
  }
@@ -14877,10 +14203,7 @@ var init_provider_cli_adapter = __esm({
14877
14203
  }
14878
14204
  const visibleAssistant = [...parsedMessages].reverse().find((m) => m.role === "assistant" && m.content.trim());
14879
14205
  if (!visibleAssistant) return false;
14880
- this.committedMessages = parsedMessages;
14881
- this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
14882
14206
  this.clearAllTimers();
14883
- this.syncMessageViews();
14884
14207
  this.responseBuffer = "";
14885
14208
  this.isWaitingForResponse = false;
14886
14209
  this.responseSettleIgnoreUntil = 0;
@@ -14892,37 +14215,34 @@ var init_provider_cli_adapter = __esm({
14892
14215
  this.setStatus("idle", "script_idle_commit");
14893
14216
  this.onStatusChange?.();
14894
14217
  this.recordTrace("script_idle_commit", {
14895
- messageCount: this.committedMessages.length,
14218
+ messageCount: parsedMessages.length,
14896
14219
  lastAssistant: summarizeCliTraceText(visibleAssistant.content, 320)
14897
14220
  });
14898
14221
  return true;
14899
14222
  }
14900
14223
  commitCurrentTranscript() {
14901
14224
  const parsed = this.parseCurrentTranscript(
14902
- this.committedMessages,
14225
+ [],
14903
14226
  this.responseBuffer,
14904
14227
  this.currentTurnScope
14905
14228
  );
14906
14229
  if (parsed && Array.isArray(parsed.messages)) {
14907
- this.committedMessages = normalizeCliParsedMessages(parsed.messages, {
14908
- committedMessages: this.committedMessages,
14909
- scope: this.currentTurnScope,
14230
+ const parsedMessages = normalizeCliParsedMessages(parsed.messages, {
14231
+ scope: null,
14910
14232
  lastOutputAt: this.lastOutputAt
14911
14233
  });
14912
- this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
14913
- this.syncMessageViews();
14914
- const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
14234
+ const lastAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
14915
14235
  if (this.currentTurnScope) {
14916
14236
  LOG.info(
14917
14237
  "CLI",
14918
- `[${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)}`
14919
14239
  );
14920
14240
  }
14921
14241
  this.recordTrace("commit_transcript", {
14922
14242
  parsedStatus: parsed.status || null,
14923
- messageCount: this.committedMessages.length,
14243
+ messageCount: parsedMessages.length,
14924
14244
  lastAssistant: lastAssistant ? summarizeCliTraceText(lastAssistant.content, 320) : "",
14925
- messages: summarizeCliTraceMessages(this.committedMessages),
14245
+ messages: summarizeCliTraceMessages(parsedMessages),
14926
14246
  ...buildCliTraceParseSnapshot({
14927
14247
  accumulatedBuffer: this.accumulatedBuffer,
14928
14248
  accumulatedRawBuffer: this.accumulatedRawBuffer,
@@ -14956,63 +14276,31 @@ var init_provider_cli_adapter = __esm({
14956
14276
  }
14957
14277
  // ─── Script Execution ──────────────────────────
14958
14278
  runParseSession() {
14959
- if (typeof this.cliScripts?.parseSession === "function") {
14960
- try {
14961
- const screenText = this.terminalScreen.getText();
14962
- const tail = this.recentOutputBuffer.slice(-500);
14963
- const parseBaseMessages = this.selectParseBaseMessages(this.committedMessages);
14964
- const input = buildCliParseInput({
14965
- accumulatedBuffer: this.accumulatedBuffer,
14966
- accumulatedRawBuffer: this.accumulatedRawBuffer,
14967
- recentOutputBuffer: this.recentOutputBuffer,
14968
- terminalScreenText: screenText,
14969
- baseMessages: parseBaseMessages,
14970
- partialResponse: this.responseBuffer,
14971
- isWaitingForResponse: this.isWaitingForResponse,
14972
- scope: this.currentTurnScope,
14973
- runtimeSettings: this.runtimeSettings
14974
- });
14975
- const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
14976
- if (session && typeof session === "object" && Array.isArray(session.messages)) {
14977
- session.messages = this.stitchParsedMessagesWithCommittedBase(
14978
- session.messages,
14979
- this.committedMessages,
14980
- parseBaseMessages
14981
- );
14982
- }
14983
- this.parseErrorMessage = null;
14984
- return session && typeof session === "object" ? session : null;
14985
- } catch (e) {
14986
- const message = e?.message || String(e);
14987
- this.parseErrorMessage = message;
14988
- LOG.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
14989
- return null;
14990
- }
14279
+ if (typeof this.cliScripts?.parseSession !== "function") {
14280
+ this.parseErrorMessage = `${this.cliType} parseSession unavailable`;
14281
+ return null;
14991
14282
  }
14992
- if (!this.cliScripts?.detectStatus && !this.cliScripts?.parseOutput) return null;
14993
14283
  try {
14994
- const tail = this.settledBuffer;
14995
- const parsedTranscript = this.parseCurrentTranscript(
14996
- this.committedMessages,
14997
- this.responseBuffer,
14998
- this.currentTurnScope
14999
- );
15000
- const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((b) => typeof b === "string" && b.trim()) ? parsedTranscript.activeModal : null;
15001
- const approval = this.runParseApproval(tail);
15002
- const modal = approval || parsedModal;
15003
- const rawStatus = this.runDetectStatus(tail);
15004
- const parsedStatus = typeof parsedTranscript?.status === "string" ? parsedTranscript.status : null;
15005
- const effectiveStatus = parsedStatus === "waiting_approval" && modal ? "waiting_approval" : rawStatus || parsedStatus || "idle";
15006
- return {
15007
- status: effectiveStatus,
15008
- messages: Array.isArray(parsedTranscript?.messages) ? parsedTranscript.messages : [],
15009
- modal,
15010
- parsedStatus
15011
- };
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;
15012
14300
  } catch (e) {
15013
14301
  const message = e?.message || String(e);
15014
14302
  this.parseErrorMessage = message;
15015
- LOG.warn("CLI", `[${this.cliType}] parseSession fallback error: ${message}`);
14303
+ LOG.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
15016
14304
  return null;
15017
14305
  }
15018
14306
  }
@@ -15062,45 +14350,14 @@ var init_provider_cli_adapter = __esm({
15062
14350
  if (this.isWaitingForResponse && this.currentTurnScope && this.currentStatus !== "stopped") return "generating";
15063
14351
  return this.currentStatus;
15064
14352
  }
15065
- suppressStaleParsedApproval(parsed, recentBuffer, screenText) {
15066
- const actionableParsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
15067
- if (!parsed || parsed?.status !== "waiting_approval" || !actionableParsedModal) {
15068
- return parsed;
15069
- }
15070
- const inApprovalCooldown = this.lastApprovalResolvedAt > 0 && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
15071
- if (!inApprovalCooldown) {
15072
- return parsed;
15073
- }
15074
- const visibleModal = this.runParseApproval(recentBuffer);
15075
- if (visibleModal) {
15076
- return parsed;
15077
- }
15078
- const detectedStatus = this.runDetectStatus(recentBuffer);
15079
- const resolvedStatus = detectedStatus && detectedStatus !== "waiting_approval" ? detectedStatus : this.isWaitingForResponse || this.currentTurnScope ? "generating" : this.currentStatus === "waiting_approval" ? "idle" : this.currentStatus;
15080
- return {
15081
- ...parsed,
15082
- status: resolvedStatus,
15083
- activeModal: null
15084
- };
15085
- }
15086
14353
  // ─── Public API (CliAdapter) ───────────────────
15087
14354
  getStatus(options = {}) {
15088
14355
  const allowParse = options.allowParse !== false;
15089
14356
  const startupModal = allowParse && this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
15090
14357
  let effectiveStatus = this.projectEffectiveStatus(startupModal);
15091
14358
  let effectiveModal = startupModal || this.activeModal;
15092
- if (allowParse && !startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
15093
- let parsed = this.getFreshParsedStatusCache();
15094
- if (!parsed && effectiveStatus !== "idle") {
15095
- const now = Date.now();
15096
- if (now - this.lastStatusHotPathParseAt >= _ProviderCliAdapter.STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS) {
15097
- this.lastStatusHotPathParseAt = now;
15098
- try {
15099
- parsed = this.getScriptParsedStatus();
15100
- } catch {
15101
- }
15102
- }
15103
- }
14359
+ if (allowParse && !startupModal && !effectiveModal) {
14360
+ const parsed = this.getFreshParsedStatusCache();
15104
14361
  const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
15105
14362
  if (parsed?.status === "waiting_approval" && parsedModal) {
15106
14363
  effectiveStatus = "waiting_approval";
@@ -15110,7 +14367,7 @@ var init_provider_cli_adapter = __esm({
15110
14367
  const bufferState = this.getBufferState();
15111
14368
  return {
15112
14369
  status: effectiveStatus,
15113
- messages: [...this.committedMessages],
14370
+ messages: [],
15114
14371
  workingDir: this.workingDir,
15115
14372
  activeModal: effectiveModal,
15116
14373
  errorMessage: this.parseErrorMessage || void 0,
@@ -15118,98 +14375,6 @@ var init_provider_cli_adapter = __esm({
15118
14375
  ...bufferState ? { bufferState } : {}
15119
14376
  };
15120
14377
  }
15121
- seedCommittedMessages(messages) {
15122
- const normalized = (Array.isArray(messages) ? messages : []).filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
15123
- role: message.role,
15124
- content: typeof message.content === "string" ? message.content : String(message.content || ""),
15125
- timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0,
15126
- receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : void 0,
15127
- kind: typeof message.kind === "string" ? message.kind : void 0,
15128
- id: typeof message.id === "string" ? message.id : void 0,
15129
- index: typeof message.index === "number" ? message.index : void 0,
15130
- providerUnitKey: typeof message.providerUnitKey === "string" ? message.providerUnitKey : void 0,
15131
- bubbleId: typeof message.bubbleId === "string" ? message.bubbleId : void 0,
15132
- bubbleState: typeof message.bubbleState === "string" ? message.bubbleState : void 0,
15133
- _turnKey: typeof message._turnKey === "string" ? message._turnKey : void 0,
15134
- meta: message.meta && typeof message.meta === "object" ? { ...message.meta } : void 0,
15135
- senderName: typeof message.senderName === "string" ? message.senderName : void 0
15136
- }));
15137
- this.committedMessages = normalized;
15138
- this.syncMessageViews();
15139
- }
15140
- getSharedCommittedPrefixLength(parsedMessages) {
15141
- const committedMessages = this.committedMessages;
15142
- const max = Math.min(parsedMessages.length, committedMessages.length);
15143
- let index = 0;
15144
- while (index < max && this.messagesShareStableIdentity(parsedMessages[index], committedMessages[index])) {
15145
- index += 1;
15146
- }
15147
- return index;
15148
- }
15149
- hydrateCommittedPrefixForParsedStatus(parsedMessages) {
15150
- const sharedPrefixLength = this.getSharedCommittedPrefixLength(parsedMessages);
15151
- if (sharedPrefixLength !== this.committedMessages.length) return null;
15152
- const committedHydratedMessages = this.committedMessages.map((message, index) => {
15153
- const timestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : this.lastOutputAt || this.currentTurnScope?.startedAt || Date.now();
15154
- const contentValue = message.content;
15155
- return {
15156
- role: message.role,
15157
- content: typeof contentValue === "string" ? contentValue : String(contentValue || ""),
15158
- timestamp,
15159
- receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp,
15160
- kind: message.kind,
15161
- id: message.id || `msg_${index}`,
15162
- index: typeof message.index === "number" ? message.index : index,
15163
- providerUnitKey: message.providerUnitKey,
15164
- bubbleId: message.bubbleId,
15165
- bubbleState: message.bubbleState,
15166
- _turnKey: message._turnKey,
15167
- meta: message.meta,
15168
- senderName: message.senderName
15169
- };
15170
- });
15171
- const extraMessages = parsedMessages.slice(sharedPrefixLength);
15172
- if (extraMessages.length === 0) return committedHydratedMessages;
15173
- const extraHydratedMessages = hydrateCliParsedMessages(extraMessages, {
15174
- committedMessages: [],
15175
- scope: this.currentTurnScope,
15176
- lastOutputAt: this.lastOutputAt
15177
- }).map((message, offset) => ({
15178
- ...message,
15179
- id: message.id || `msg_${sharedPrefixLength + offset}`,
15180
- index: typeof message.index === "number" ? message.index : sharedPrefixLength + offset
15181
- }));
15182
- return [...committedHydratedMessages, ...extraHydratedMessages];
15183
- }
15184
- hydrateParsedMessagesForStatus(parsedMessages) {
15185
- return this.hydrateCommittedPrefixForParsedStatus(parsedMessages) || hydrateCliParsedMessages(parsedMessages, {
15186
- committedMessages: this.committedMessages,
15187
- scope: this.currentTurnScope,
15188
- lastOutputAt: this.lastOutputAt
15189
- });
15190
- }
15191
- buildCommittedChatMessages() {
15192
- return this.committedMessages.map((message, index) => {
15193
- const rawContentValue = message.content;
15194
- const rawContent = typeof rawContentValue === "string" ? rawContentValue : String(rawContentValue || "");
15195
- const content = message.role === "assistant" && (message.kind || "standard") === "standard" ? sanitizeCliStandardMessageContent(rawContent) : rawContent;
15196
- return buildChatMessage({
15197
- role: message.role,
15198
- content,
15199
- timestamp: message.timestamp,
15200
- kind: message.kind,
15201
- meta: message.meta,
15202
- senderName: message.senderName,
15203
- id: message.id || `msg_${index}`,
15204
- index: typeof message.index === "number" ? message.index : index,
15205
- providerUnitKey: message.providerUnitKey,
15206
- bubbleId: message.bubbleId,
15207
- bubbleState: message.bubbleState,
15208
- _turnKey: message._turnKey,
15209
- receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
15210
- });
15211
- });
15212
- }
15213
14378
  /**
15214
14379
  * Script-based full parse — returns ReadChatResult.
15215
14380
  * Called by command handler / dashboard for rich content rendering.
@@ -15217,125 +14382,30 @@ var init_provider_cli_adapter = __esm({
15217
14382
  getScriptParsedStatus() {
15218
14383
  const screenText = this.readTerminalScreenText();
15219
14384
  const cached2 = this.parsedStatusCache;
15220
- 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) {
15221
14386
  return cached2.result;
15222
14387
  }
15223
- const parsed = this.parseCurrentTranscript(
15224
- this.committedMessages,
15225
- this.responseBuffer,
15226
- this.currentTurnScope,
15227
- screenText
15228
- );
15229
- const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
15230
- if (parsedModal && parsed?.status === "waiting_approval") {
15231
- this.activeModal = parsedModal;
15232
- this.isWaitingForResponse = true;
15233
- if (this.currentStatus !== "waiting_approval") {
15234
- this.setStatus("waiting_approval", "parsed_waiting_approval");
15235
- this.onStatusChange?.();
15236
- }
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`);
15237
14391
  }
15238
- if (parsed && Array.isArray(parsed.messages) && this.provider.allowInputDuringGeneration === true) {
15239
- const hydratedForCommit = normalizeCliParsedMessages(parsed.messages, {
15240
- committedMessages: this.committedMessages,
15241
- 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,
15242
14400
  lastOutputAt: this.lastOutputAt
15243
- });
15244
- const fakeSession = {
15245
- status: parsed.status || "idle",
15246
- messages: parsed.messages,
15247
- modal: parsedModal,
15248
- parsedStatus: parsed.status || null
15249
- };
15250
- if (this.maybeCommitVisibleIdleTranscript(fakeSession, hydratedForCommit)) {
15251
- return this.getScriptParsedStatus();
15252
- }
15253
- }
15254
- const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
15255
- let result;
15256
- if (parsed && Array.isArray(parsed.messages)) {
15257
- const parsedHydratedMessages = this.hydrateParsedMessagesForStatus(parsed.messages);
15258
- const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === "assistant" && typeof message.content === "string" && message.content.trim());
15259
- 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");
15260
- if (shouldAdoptParsedIdleReplay) {
15261
- this.committedMessages = this.getSharedCommittedPrefixLength(parsed.messages) === this.committedMessages.length ? parsedHydratedMessages.map((message) => ({
15262
- role: message.role,
15263
- content: typeof message.content === "string" ? message.content : String(message.content || ""),
15264
- timestamp: message.timestamp,
15265
- receivedAt: message.receivedAt,
15266
- kind: message.kind,
15267
- id: message.id,
15268
- index: message.index,
15269
- meta: message.meta,
15270
- senderName: message.senderName
15271
- })) : normalizeCliParsedMessages(parsed.messages, {
15272
- committedMessages: this.committedMessages,
15273
- scope: this.currentTurnScope,
15274
- lastOutputAt: this.lastOutputAt
15275
- });
15276
- this.syncMessageViews();
15277
- if (this.currentStatus !== "idle" || this.isWaitingForResponse) {
15278
- this.responseBuffer = "";
15279
- this.isWaitingForResponse = false;
15280
- this.responseSettleIgnoreUntil = 0;
15281
- this.submitRetryUsed = false;
15282
- this.submitRetryPromptSnippet = "";
15283
- this.finishRetryCount = 0;
15284
- this.currentTurnScope = null;
15285
- this.activeModal = null;
15286
- this.setStatus("idle", "parsed_idle_replay_commit");
15287
- this.onStatusChange?.();
15288
- }
15289
- }
15290
- const shouldPreferCommittedHistoryReplay = !this.currentTurnScope && !this.activeModal && this.committedMessages.length > parsedHydratedMessages.length;
15291
- const shouldPreferCommittedIdleReplay = shouldPreferCommittedMessages && !shouldAdoptParsedIdleReplay;
15292
- const hydratedMessages = shouldPreferCommittedIdleReplay || shouldPreferCommittedHistoryReplay ? this.buildCommittedChatMessages() : parsedHydratedMessages;
15293
- result = {
15294
- id: parsed.id || "cli_session",
15295
- status: parsed.status || this.currentStatus,
15296
- title: parsed.title || this.cliName,
15297
- messages: hydratedMessages,
15298
- activeModal: parsed.activeModal ?? this.activeModal,
15299
- providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
15300
- ...this.getBufferState() ? { bufferState: this.getBufferState() } : {},
15301
- ...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
15302
- };
15303
- } else {
15304
- const messages = [...this.committedMessages];
15305
- const bufferState = this.getBufferState();
15306
- result = {
15307
- id: "cli_session",
15308
- status: this.currentStatus,
15309
- title: this.cliName,
15310
- messages: messages.map((message, index) => buildChatMessage({
15311
- ...message,
15312
- id: message.id || `msg_${index}`,
15313
- index: typeof message.index === "number" ? message.index : index,
15314
- receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
15315
- })),
15316
- activeModal: this.activeModal,
15317
- ...bufferState ? { bufferState } : {}
15318
- };
15319
- }
15320
- const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
15321
- const shouldClampStaleGeneratingToIdle = result?.status === "generating" && this.currentStatus === "idle" && !this.currentTurnScope && !result?.activeModal && hasVisibleAssistantMessage && !hasVisibleInterruptPrompt(screenText);
15322
- if (shouldClampStaleGeneratingToIdle) {
15323
- result = {
15324
- ...result,
15325
- status: "idle",
15326
- messages: Array.isArray(result.messages) ? result.messages.map((message) => {
15327
- if (message?.role !== "assistant" || !message?.meta?.streaming) return message;
15328
- const nextMeta = { ...message.meta || {} };
15329
- delete nextMeta.streaming;
15330
- return {
15331
- ...message,
15332
- ...Object.keys(nextMeta).length > 0 ? { meta: nextMeta } : { meta: void 0 }
15333
- };
15334
- }) : result.messages
15335
- };
15336
- }
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
+ };
15337
14408
  this.parsedStatusCache = {
15338
- committedMessagesRef: this.committedMessages,
15339
14409
  responseBuffer: this.responseBuffer,
15340
14410
  currentTurnScope: this.currentTurnScope,
15341
14411
  recentOutputBuffer: this.recentOutputBuffer,
@@ -15358,7 +14428,7 @@ var init_provider_cli_adapter = __esm({
15358
14428
  accumulatedRawBuffer: this.accumulatedRawBuffer,
15359
14429
  recentOutputBuffer: this.recentOutputBuffer,
15360
14430
  terminalScreenText: this.terminalScreen.getText(),
15361
- baseMessages: this.committedMessages,
14431
+ baseMessages: [],
15362
14432
  partialResponse: this.responseBuffer,
15363
14433
  isWaitingForResponse: this.isWaitingForResponse,
15364
14434
  scope: this.currentTurnScope,
@@ -15369,46 +14439,8 @@ var init_provider_cli_adapter = __esm({
15369
14439
  args: args && typeof args === "object" ? { ...args } : {}
15370
14440
  }));
15371
14441
  }
15372
- parseCurrentTranscript(baseMessages, partialResponse, scope, screenTextOverride) {
15373
- if (!this.cliScripts?.parseOutput) {
15374
- this.parseErrorMessage = null;
15375
- return null;
15376
- }
15377
- try {
15378
- const screenText = typeof screenTextOverride === "string" ? screenTextOverride : this.terminalScreen.getText();
15379
- const parseBaseMessages = this.selectParseBaseMessages(baseMessages);
15380
- const input = buildCliParseInput({
15381
- accumulatedBuffer: this.accumulatedBuffer,
15382
- accumulatedRawBuffer: this.accumulatedRawBuffer,
15383
- recentOutputBuffer: this.recentOutputBuffer,
15384
- terminalScreenText: screenText,
15385
- baseMessages: parseBaseMessages,
15386
- partialResponse,
15387
- isWaitingForResponse: this.isWaitingForResponse,
15388
- scope,
15389
- runtimeSettings: this.runtimeSettings
15390
- });
15391
- const parsed = this.cliScripts.parseOutput(input);
15392
- if (parsed && typeof parsed === "object") {
15393
- Object.assign(parsed, validateReadChatResultPayload(parsed, `${this.cliType} parseOutput`));
15394
- }
15395
- const normalizedParsed = this.suppressStaleParsedApproval(parsed, input.recentBuffer, input.screenText);
15396
- if (normalizedParsed && Array.isArray(normalizedParsed.messages)) {
15397
- normalizedParsed.messages = this.stitchParsedMessagesWithCommittedBase(
15398
- normalizedParsed.messages,
15399
- baseMessages,
15400
- parseBaseMessages
15401
- );
15402
- this.trimLastAssistantEcho(normalizedParsed.messages, scope?.prompt || getLastUserPromptText(baseMessages));
15403
- }
15404
- this.parseErrorMessage = null;
15405
- return normalizedParsed;
15406
- } catch (e) {
15407
- const message = e?.message || String(e);
15408
- this.parseErrorMessage = message;
15409
- LOG.warn("CLI", `[${this.cliType}] parseOutput error: ${message}`);
15410
- throw e;
15411
- }
14442
+ parseCurrentTranscript(_baseMessages, _partialResponse, _scope, _screenTextOverride) {
14443
+ return this.runParseSession();
15412
14444
  }
15413
14445
  /** Whether this adapter has CLI scripts loaded */
15414
14446
  hasCliScripts() {
@@ -15470,8 +14502,6 @@ var init_provider_cli_adapter = __esm({
15470
14502
  commitSendUserTurn(state) {
15471
14503
  if (state.didCommitUserTurn) return;
15472
14504
  state.didCommitUserTurn = true;
15473
- this.committedMessages.push({ role: "user", content: state.text, timestamp: Date.now() });
15474
- this.syncMessageViews();
15475
14505
  }
15476
14506
  armResponseTimeout() {
15477
14507
  if (this.responseTimeout) clearTimeout(this.responseTimeout);
@@ -15663,11 +14693,6 @@ var init_provider_cli_adapter = __esm({
15663
14693
  }
15664
14694
  })() : null;
15665
14695
  const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
15666
- const parsedMessagesBeforeSend = Array.isArray(parsedStatusBeforeSend?.messages) ? parsedStatusBeforeSend.messages.filter((message) => message && (message.role === "user" || message.role === "assistant")) : [];
15667
- const shouldCommitParsedIdleBeforeSend = !allowInputDuringGeneration && parsedSessionStatus === "idle" && parsedMessagesBeforeSend.length > this.committedMessages.length && parsedMessagesBeforeSend.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
15668
- if (shouldCommitParsedIdleBeforeSend) {
15669
- this.commitCurrentTranscript();
15670
- }
15671
14696
  if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
15672
14697
  throw new Error(`${this.cliName} is still processing the previous prompt`);
15673
14698
  }
@@ -15773,9 +14798,6 @@ var init_provider_cli_adapter = __esm({
15773
14798
  activeModal: this.activeModal,
15774
14799
  parseErrorMessage: this.parseErrorMessage,
15775
14800
  messageCounts: {
15776
- committed: this.committedMessages.length,
15777
- structured: this.structuredMessages.length,
15778
- visible: this.messages.length,
15779
14801
  parsedCache: Array.isArray(parsedResult?.messages) ? parsedResult.messages.length : void 0
15780
14802
  },
15781
14803
  buffers: {
@@ -15826,8 +14848,7 @@ var init_provider_cli_adapter = __esm({
15826
14848
  responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
15827
14849
  responseEpoch: this.responseEpoch,
15828
14850
  resizeSuppressUntil: this.resizeSuppressUntil,
15829
- lastApprovalResolvedAt: this.lastApprovalResolvedAt,
15830
- committedMessagesChangedAt: this.committedMessagesChangedAt
14851
+ lastApprovalResolvedAt: this.lastApprovalResolvedAt
15831
14852
  },
15832
14853
  finish: {
15833
14854
  idleFinishCandidate: this.idleFinishCandidate,
@@ -15952,8 +14973,6 @@ var init_provider_cli_adapter = __esm({
15952
14973
  }
15953
14974
  clearHistory() {
15954
14975
  this.clearIdleFinishCandidate("clear_history");
15955
- this.committedMessages = [];
15956
- this.syncMessageViews();
15957
14976
  this.accumulatedBuffer = "";
15958
14977
  this.accumulatedRawBuffer = "";
15959
14978
  this.currentTurnScope = null;
@@ -15994,7 +15013,7 @@ var init_provider_cli_adapter = __esm({
15994
15013
  }
15995
15014
  resolveModal(buttonIndex) {
15996
15015
  let modal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
15997
- if (!modal && typeof this.cliScripts?.parseOutput === "function") {
15016
+ if (!modal && typeof this.cliScripts?.parseSession === "function") {
15998
15017
  try {
15999
15018
  const parsed = this.getScriptParsedStatus();
16000
15019
  const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
@@ -16061,10 +15080,8 @@ var init_provider_cli_adapter = __esm({
16061
15080
  startupParseGate: this.startupParseGate,
16062
15081
  spawnAt: this.spawnAt,
16063
15082
  workingDir: this.workingDir,
16064
- messages: this.messages,
16065
- committedMessages: this.committedMessages,
16066
- structuredMessages: this.structuredMessages,
16067
- messageCount: this.committedMessages.length,
15083
+ messages: [],
15084
+ messageCount: 0,
16068
15085
  screenText: screenText.slice(-4e3),
16069
15086
  currentTurnScope: this.currentTurnScope,
16070
15087
  startupBuffer: this.startupBuffer.slice(-4e3),
@@ -16116,7 +15133,7 @@ var init_provider_cli_adapter = __esm({
16116
15133
  lifecycleStatus: this.isWaitingForResponse ? "awaiting_response" : "idle",
16117
15134
  activeModal: this.activeModal,
16118
15135
  currentTurnScope: this.currentTurnScope,
16119
- messages: summarizeCliTraceMessages(this.committedMessages, 5)
15136
+ messages: []
16120
15137
  };
16121
15138
  }
16122
15139
  getProviderResolutionMeta() {
@@ -16409,17 +15426,11 @@ var init_cli_provider_instance = __esm({
16409
15426
  }
16410
15427
  const runtime = this.adapter.getRuntimeMetadata();
16411
15428
  this.maybeAppendRuntimeRecoveryMessage(runtime);
16412
- 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 : [];
16413
15430
  const historyMessageCount = Number.isFinite(parsedStatus?.historyMessageCount) ? Math.max(0, Number(parsedStatus.historyMessageCount)) : null;
16414
15431
  if (historyMessageCount !== null) {
16415
15432
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
16416
15433
  }
16417
- const committedMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
16418
- const isActiveNonIdle = adapterStatus.status !== "idle";
16419
- const shouldApplyCommittedFloor = parsedMessages.length < committedMessages.length && (adapterStatus.status === "waiting_approval" || isActiveNonIdle && historyMessageCount === null);
16420
- if (shouldApplyCommittedFloor) {
16421
- parsedMessages = normalizeChatMessages(committedMessages);
16422
- }
16423
15434
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
16424
15435
  const canonicalBackedHistory = this.syncCanonicalSavedHistoryIfNeeded();
16425
15436
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
@@ -16512,11 +15523,9 @@ var init_cli_provider_instance = __esm({
16512
15523
  const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
16513
15524
  const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
16514
15525
  const runtime = this.adapter.getRuntimeMetadata();
16515
- const lastCommittedMessageActivityAt = typeof this.adapter.getLastCommittedMessageActivityAt === "function" ? this.adapter.getLastCommittedMessageActivityAt() : 0;
16516
15526
  return {
16517
15527
  id: this.instanceId,
16518
15528
  status: visibleStatus,
16519
- lastMessageAt: lastCommittedMessageActivityAt || void 0,
16520
15529
  runtimeLifecycle: runtime?.lifecycle ?? null,
16521
15530
  runtimeSurfaceKind: runtime?.surfaceKind,
16522
15531
  runtimeRestoredFromStorage: runtime?.restoredFromStorage === true,
@@ -16622,7 +15631,7 @@ var init_cli_provider_instance = __esm({
16622
15631
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
16623
15632
  const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
16624
15633
  const partial2 = this.adapter.getPartialResponse();
16625
- const progressFingerprint = newStatus === "generating" ? `${partial2 || ""}::${adapterStatus.messages.at(-1)?.content || ""}`.slice(-2e3) : void 0;
15634
+ const progressFingerprint = newStatus === "generating" ? `${partial2 || ""}`.slice(-2e3) : void 0;
16626
15635
  const previousStatus = this.lastStatus;
16627
15636
  if (newStatus !== this.lastStatus) {
16628
15637
  LOG.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
@@ -17068,18 +16077,6 @@ ${effect.notification.body || ""}`.trim();
17068
16077
  receivedAt: message.receivedAt
17069
16078
  }));
17070
16079
  this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
17071
- if (restoredHistory.messages.length > 0) {
17072
- this.adapter.seedCommittedMessages(
17073
- restoredHistory.messages.map((message) => ({
17074
- role: message.role,
17075
- content: message.content,
17076
- timestamp: message.receivedAt,
17077
- receivedAt: message.receivedAt,
17078
- kind: message.kind,
17079
- senderName: message.senderName
17080
- }))
17081
- );
17082
- }
17083
16080
  }
17084
16081
  getProbeDirectories() {
17085
16082
  const dirs = /* @__PURE__ */ new Set();
@@ -39307,13 +38304,24 @@ async function launchWithCdp(options = {}) {
39307
38304
  break;
39308
38305
  }
39309
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
+ }
39310
38318
  return {
39311
38319
  success: true,
39312
38320
  ideId: targetIde.id,
39313
38321
  ideName: targetIde.displayName,
39314
38322
  port,
39315
38323
  action: alreadyRunning ? "restarted" : "started",
39316
- 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}`
39317
38325
  };
39318
38326
  } catch (e) {
39319
38327
  return {
@@ -41310,9 +40318,6 @@ var init_ipc_protocol = __esm({
41310
40318
  });
41311
40319
 
41312
40320
  // ../../oss/packages/daemon-core/src/chat/subscription-updates.ts
41313
- function normalizeSyncMode(syncMode) {
41314
- return syncMode === "append" || syncMode === "replace_tail" || syncMode === "noop" || syncMode === "full" ? syncMode : "full";
41315
- }
41316
40321
  function normalizeModalButtons(value) {
41317
40322
  return Array.isArray(value) ? value.filter((button) => typeof button === "string") : [];
41318
40323
  }
@@ -41339,55 +40344,39 @@ function normalizeSessionModalFields(activeModal) {
41339
40344
  modalButtons: normalizeModalButtons(activeModal.buttons)
41340
40345
  };
41341
40346
  }
41342
- function buildNextChatCursor(cursor, result) {
41343
- return {
41344
- knownMessageCount: Math.max(0, Number(result.totalMessages || cursor.knownMessageCount)),
41345
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : cursor.lastMessageSignature,
41346
- tailLimit: cursor.tailLimit
41347
- };
41348
- }
41349
40347
  function prepareSessionChatTailUpdate(input) {
41350
40348
  const result = input.result;
41351
- if (!result?.success || result.syncMode === "noop") {
40349
+ if (!result?.success) {
41352
40350
  return {
41353
- cursor: result?.success ? buildNextChatCursor(input.cursor, result) : input.cursor,
40351
+ cursor: input.cursor,
41354
40352
  seq: input.seq,
41355
40353
  lastDeliveredSignature: input.lastDeliveredSignature,
41356
40354
  update: null
41357
40355
  };
41358
40356
  }
41359
- const syncMode = normalizeSyncMode(result.syncMode);
41360
- const cursor = {
41361
- knownMessageCount: Math.max(0, Number(result.totalMessages || 0)),
41362
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : "",
41363
- tailLimit: input.cursor.tailLimit
41364
- };
40357
+ const messages = Array.isArray(result.messages) ? result.messages : [];
41365
40358
  const title = typeof result.title === "string" ? result.title : void 0;
41366
40359
  const activeModal = normalizeChatTailActiveModal(result.activeModal);
41367
40360
  const status = typeof result.status === "string" ? result.status : "idle";
41368
40361
  const deliverySignature = buildChatTailDeliverySignature({
41369
40362
  sessionId: input.sessionId,
41370
40363
  ...input.historySessionId ? { historySessionId: input.historySessionId } : {},
41371
- messages: Array.isArray(result.messages) ? result.messages : [],
40364
+ messages,
41372
40365
  status,
41373
40366
  ...title ? { title } : {},
41374
- ...activeModal ? { activeModal } : {},
41375
- syncMode,
41376
- replaceFrom: Number(result.replaceFrom || 0),
41377
- totalMessages: Number(result.totalMessages || 0),
41378
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
40367
+ ...activeModal ? { activeModal } : {}
41379
40368
  });
41380
40369
  const seq = input.seq + 1;
41381
40370
  if (deliverySignature === input.lastDeliveredSignature) {
41382
40371
  return {
41383
- cursor,
40372
+ cursor: input.cursor,
41384
40373
  seq,
41385
40374
  lastDeliveredSignature: input.lastDeliveredSignature,
41386
40375
  update: null
41387
40376
  };
41388
40377
  }
41389
40378
  return {
41390
- cursor,
40379
+ cursor: input.cursor,
41391
40380
  seq,
41392
40381
  lastDeliveredSignature: deliverySignature,
41393
40382
  update: {
@@ -41398,14 +40387,10 @@ function prepareSessionChatTailUpdate(input) {
41398
40387
  ...input.interactionId ? { interactionId: input.interactionId } : {},
41399
40388
  seq,
41400
40389
  timestamp: input.timestamp,
41401
- messages: Array.isArray(result.messages) ? result.messages : [],
40390
+ messages,
41402
40391
  status,
41403
40392
  ...title ? { title } : {},
41404
- ...activeModal ? { activeModal } : {},
41405
- syncMode,
41406
- replaceFrom: Number(result.replaceFrom || 0),
41407
- totalMessages: Number(result.totalMessages || 0),
41408
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
40393
+ ...activeModal ? { activeModal } : {}
41409
40394
  }
41410
40395
  };
41411
40396
  }
@@ -46143,7 +45128,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
46143
45128
  lines.push("Provider category: `cli`");
46144
45129
  lines.push("");
46145
45130
  const funcToFile = {
46146
- parseOutput: "parse_output.js",
45131
+ parseSession: "parse_session.js",
46147
45132
  detectStatus: "detect_status.js",
46148
45133
  parseApproval: "parse_approval.js"
46149
45134
  };
@@ -46232,7 +45217,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
46232
45217
  lines.push("");
46233
45218
  lines.push("| Function | Input | Return |");
46234
45219
  lines.push("|---|---|---|");
46235
- 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 }` |");
46236
45221
  lines.push("| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |");
46237
45222
  lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
46238
45223
  lines.push("");
@@ -46452,7 +45437,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
46452
45437
  lines.push("");
46453
45438
  lines.push("## Required Validation");
46454
45439
  lines.push("1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.");
46455
- 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.");
46456
45441
  lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
46457
45442
  lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
46458
45443
  lines.push("5. Confirm the Python file was actually created and executed, not just described in chat text.");
@@ -47751,7 +46736,7 @@ var init_dev_server = __esm({
47751
46736
  lines.push("Provider category: `cli`");
47752
46737
  lines.push("");
47753
46738
  const funcToFile = {
47754
- parseOutput: "parse_output.js",
46739
+ parseSession: "parse_session.js",
47755
46740
  detectStatus: "detect_status.js",
47756
46741
  parseApproval: "parse_approval.js"
47757
46742
  };
@@ -47840,7 +46825,7 @@ var init_dev_server = __esm({
47840
46825
  lines.push("");
47841
46826
  lines.push("| Function | Input | Return |");
47842
46827
  lines.push("|---|---|---|");
47843
- 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 }` |");
47844
46829
  lines.push("| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |");
47845
46830
  lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
47846
46831
  lines.push("");
@@ -47935,7 +46920,7 @@ var init_dev_server = __esm({
47935
46920
  lines.push("");
47936
46921
  lines.push("## Required Validation");
47937
46922
  lines.push("1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.");
47938
- 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.");
47939
46924
  lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
47940
46925
  lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
47941
46926
  lines.push("5. Confirm the Python file was actually created and executed, not just described in chat text.");
@@ -50048,8 +49033,6 @@ function handleSubscribe(peerId, msg, peers, handlers) {
50048
49033
  params,
50049
49034
  seq: 0,
50050
49035
  cursor: {
50051
- knownMessageCount: Math.max(0, Number(params.knownMessageCount || 0)),
50052
- lastMessageSignature: typeof params.lastMessageSignature === "string" ? params.lastMessageSignature : "",
50053
49036
  tailLimit: Math.max(0, Number(params.tailLimit || 0))
50054
49037
  },
50055
49038
  lastDeliveredSignature: ""
@@ -51089,12 +50072,8 @@ ${e?.stack || ""}`);
51089
50072
  sessionId: subscription.params.targetSessionId,
51090
50073
  seq: subscription.seq,
51091
50074
  timestamp: Date.now(),
51092
- syncMode: "noop",
51093
50075
  messages: [],
51094
50076
  status: "",
51095
- replaceFrom: 0,
51096
- totalMessages: 0,
51097
- lastMessageSignature: "",
51098
50077
  error: error48?.message || "chat_tail build failed"
51099
50078
  };
51100
50079
  this.screenshotSender.sendTopicUpdateToPeer(peer, errorUpdate);
@@ -59271,7 +58250,7 @@ var init_adhdev_daemon = __esm({
59271
58250
  init_version();
59272
58251
  init_src();
59273
58252
  init_runtime_defaults();
59274
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.64" });
58253
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.65" });
59275
58254
  AdhdevDaemon = class _AdhdevDaemon {
59276
58255
  localHttpServer = null;
59277
58256
  localWss = null;
@@ -59431,8 +58410,6 @@ var init_adhdev_daemon = __esm({
59431
58410
  const result = await this.components.router.execute("read_chat", {
59432
58411
  targetSessionId: subscription.params.targetSessionId,
59433
58412
  ...subscription.params.historySessionId ? { historySessionId: subscription.params.historySessionId } : {},
59434
- knownMessageCount: subscription.cursor.knownMessageCount,
59435
- lastMessageSignature: subscription.cursor.lastMessageSignature,
59436
58413
  ...subscription.cursor.tailLimit > 0 ? { tailLimit: subscription.cursor.tailLimit } : {}
59437
58414
  }, "p2p");
59438
58415
  const interactionId = this.getSessionInteractionId(subscription.params.targetSessionId);
@@ -59460,9 +58437,7 @@ var init_adhdev_daemon = __esm({
59460
58437
  level: "info",
59461
58438
  sessionId: subscription.params.targetSessionId,
59462
58439
  payload: {
59463
- syncMode: prepared.update.syncMode,
59464
- totalMessages: prepared.update.totalMessages,
59465
- replaceFrom: prepared.update.replaceFrom,
58440
+ returnedMessages: prepared.update.messages.length,
59466
58441
  hasModal: !!prepared.update.activeModal,
59467
58442
  hasTitle: typeof prepared.update.title === "string"
59468
58443
  }