adhdev 0.9.63 → 0.9.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -9162,10 +9162,6 @@ function buildChatTailDeliverySignature(payload) {
9162
9162
  payload.historySessionId || "",
9163
9163
  payload.status,
9164
9164
  payload.title || "",
9165
- payload.syncMode,
9166
- String(payload.replaceFrom),
9167
- String(payload.totalMessages),
9168
- payload.lastMessageSignature,
9169
9165
  payload.activeModal ? `${payload.activeModal.message}|${payload.activeModal.buttons.join("")}` : "",
9170
9166
  stringifySignatureMessages(payload.messages)
9171
9167
  ]);
@@ -9283,99 +9279,13 @@ function parseMaybeJson(value) {
9283
9279
  return value;
9284
9280
  }
9285
9281
  }
9286
- function getChatMessageSignature(message) {
9287
- return buildChatMessageSignature(message);
9288
- }
9289
- function normalizeReadChatCursor(args) {
9290
- const knownMessageCount = Math.max(0, Number(args?.knownMessageCount || 0));
9291
- const lastMessageSignature = typeof args?.lastMessageSignature === "string" ? args.lastMessageSignature : "";
9292
- const tailLimit = Math.max(0, Number(args?.tailLimit || 0));
9293
- return { knownMessageCount, lastMessageSignature, tailLimit };
9282
+ function normalizeReadChatTailLimit(args) {
9283
+ const value = Number(args?.tailLimit || 0);
9284
+ return Number.isFinite(value) ? Math.max(0, value) : 0;
9294
9285
  }
9295
9286
  function normalizeReadChatMessages(payload) {
9296
9287
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
9297
- return normalizeChatMessages(messages);
9298
- }
9299
- function normalizeReadChatReplayTextContent(content) {
9300
- return flattenContent(content || "").replace(/\s+/g, " ").trim();
9301
- }
9302
- function getReadChatReplayCollapseInfo(message) {
9303
- if (!message) return null;
9304
- const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
9305
- const kind = typeof message.kind === "string" ? message.kind.trim().toLowerCase() : "standard";
9306
- const senderName = typeof message.senderName === "string" ? message.senderName.trim().toLowerCase() : "";
9307
- const collapsible = role === "assistant" || role === "system";
9308
- if (!collapsible) return { role, kind, senderName, content: "", signature: "", collapsible };
9309
- const content = normalizeReadChatReplayTextContent(message.content);
9310
- return {
9311
- role,
9312
- kind,
9313
- senderName,
9314
- content,
9315
- signature: `${role}:${kind}:${senderName}:${content}`,
9316
- collapsible
9317
- };
9318
- }
9319
- function isStableReadChatAssistantAnswerInfo(info) {
9320
- if (!info) return false;
9321
- if (info.role !== "assistant") return false;
9322
- if (info.kind && info.kind !== "standard") return false;
9323
- if (info.content.length < 160) return false;
9324
- if (/^(bash|shell|terminal) command\b/i.test(info.content)) return false;
9325
- return true;
9326
- }
9327
- function isReplayedAssistantAnswerAfterStableAnswerInfo(info, stableContent) {
9328
- if (!info || !stableContent) return false;
9329
- if (info.role !== "assistant") return false;
9330
- if (info.kind && info.kind !== "standard") return false;
9331
- const content = info.content;
9332
- if (content.length < 80 || stableContent.length < 80) return false;
9333
- return content === stableContent || content.startsWith(stableContent) || stableContent.startsWith(content);
9334
- }
9335
- function collapseReplayDuplicatesFromReadChat(messages) {
9336
- const collapsed = [];
9337
- const replaySignaturesInCurrentTurn = /* @__PURE__ */ new Set();
9338
- let stableAssistantAnswerContentInCurrentTurn = "";
9339
- let stableAssistantAnswerCollapsedIndex = -1;
9340
- let stableAssistantAnswerHadInterveningActivity = false;
9341
- let previousReplaySignature = "";
9342
- for (const message of messages) {
9343
- const info = getReadChatReplayCollapseInfo(message);
9344
- if (info?.role === "user") {
9345
- replaySignaturesInCurrentTurn.clear();
9346
- stableAssistantAnswerContentInCurrentTurn = "";
9347
- stableAssistantAnswerCollapsedIndex = -1;
9348
- stableAssistantAnswerHadInterveningActivity = false;
9349
- previousReplaySignature = "";
9350
- }
9351
- if (info?.collapsible && info.signature) {
9352
- if (previousReplaySignature === info.signature) continue;
9353
- if (replaySignaturesInCurrentTurn.has(info.signature)) continue;
9354
- if (isReplayedAssistantAnswerAfterStableAnswerInfo(info, stableAssistantAnswerContentInCurrentTurn)) {
9355
- 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);
9356
- if (isAdjacentFullerAssistantAnswer) {
9357
- collapsed[stableAssistantAnswerCollapsedIndex] = message;
9358
- replaySignaturesInCurrentTurn.add(info.signature);
9359
- stableAssistantAnswerContentInCurrentTurn = info.content;
9360
- previousReplaySignature = info.signature;
9361
- }
9362
- continue;
9363
- }
9364
- }
9365
- collapsed.push(message);
9366
- previousReplaySignature = info?.collapsible ? info.signature : "";
9367
- if (info?.collapsible && info.signature) {
9368
- replaySignaturesInCurrentTurn.add(info.signature);
9369
- }
9370
- if (isStableReadChatAssistantAnswerInfo(info)) {
9371
- stableAssistantAnswerContentInCurrentTurn = info?.content || "";
9372
- stableAssistantAnswerCollapsedIndex = collapsed.length - 1;
9373
- stableAssistantAnswerHadInterveningActivity = false;
9374
- } else if (stableAssistantAnswerContentInCurrentTurn && info?.role === "assistant" && (!info.kind || info.kind !== "standard")) {
9375
- stableAssistantAnswerHadInterveningActivity = true;
9376
- }
9377
- }
9378
- return collapsed;
9288
+ return messages;
9379
9289
  }
9380
9290
  function deriveHistoryDedupKey(message) {
9381
9291
  const unitKey = typeof message._unitKey === "string" ? message._unitKey.trim() : "";
@@ -9400,102 +9310,12 @@ function toHistoryPersistedMessages(messages) {
9400
9310
  historyDedupKey: deriveHistoryDedupKey(message)
9401
9311
  }));
9402
9312
  }
9403
- function findLastMessageIndexBySignature(messages, signature) {
9404
- if (!signature) return -1;
9405
- for (let index = messages.length - 1; index >= 0; index -= 1) {
9406
- if (getChatMessageSignature(messages[index]) === signature) {
9407
- return index;
9408
- }
9409
- }
9410
- return -1;
9411
- }
9412
- function buildBoundedTailSync(messages, cursor) {
9313
+ function buildFullTail(messages, tailLimit) {
9413
9314
  const totalMessages = messages.length;
9414
- const tailMessages = cursor.tailLimit > 0 && totalMessages > cursor.tailLimit ? messages.slice(-cursor.tailLimit) : messages;
9315
+ const tailMessages = tailLimit > 0 ? messages.slice(-tailLimit) : messages;
9415
9316
  return {
9416
- syncMode: "full",
9417
- replaceFrom: 0,
9418
9317
  messages: tailMessages,
9419
- totalMessages,
9420
- lastMessageSignature: getChatMessageSignature(messages[totalMessages - 1])
9421
- };
9422
- }
9423
- function computeReadChatSync(messages, cursor) {
9424
- const totalMessages = messages.length;
9425
- const lastMessageSignature = getChatMessageSignature(messages[totalMessages - 1]);
9426
- const { knownMessageCount, lastMessageSignature: knownSignature } = cursor;
9427
- if (!knownMessageCount || !knownSignature) {
9428
- return {
9429
- syncMode: "full",
9430
- replaceFrom: 0,
9431
- messages,
9432
- totalMessages,
9433
- lastMessageSignature
9434
- };
9435
- }
9436
- if (knownMessageCount > totalMessages) {
9437
- return {
9438
- syncMode: "full",
9439
- replaceFrom: 0,
9440
- messages,
9441
- totalMessages,
9442
- lastMessageSignature
9443
- };
9444
- }
9445
- if (knownMessageCount === totalMessages && knownSignature === lastMessageSignature) {
9446
- return {
9447
- syncMode: "noop",
9448
- replaceFrom: totalMessages,
9449
- messages: [],
9450
- totalMessages,
9451
- lastMessageSignature
9452
- };
9453
- }
9454
- if (cursor.tailLimit > 0 && knownSignature === lastMessageSignature) {
9455
- const requestedTailCount = Math.min(totalMessages, cursor.tailLimit);
9456
- if (knownMessageCount >= requestedTailCount) {
9457
- return {
9458
- syncMode: "noop",
9459
- replaceFrom: totalMessages,
9460
- messages: [],
9461
- totalMessages,
9462
- lastMessageSignature
9463
- };
9464
- }
9465
- return buildBoundedTailSync(messages, cursor);
9466
- }
9467
- if (knownMessageCount < totalMessages) {
9468
- const anchorSignature = getChatMessageSignature(messages[knownMessageCount - 1]);
9469
- if (anchorSignature === knownSignature) {
9470
- return {
9471
- syncMode: "append",
9472
- replaceFrom: knownMessageCount,
9473
- messages: messages.slice(knownMessageCount),
9474
- totalMessages,
9475
- lastMessageSignature
9476
- };
9477
- }
9478
- if (cursor.tailLimit > 0) {
9479
- const signatureIndex = findLastMessageIndexBySignature(messages, knownSignature);
9480
- if (signatureIndex >= 0) {
9481
- return {
9482
- syncMode: "append",
9483
- replaceFrom: knownMessageCount,
9484
- messages: messages.slice(signatureIndex + 1),
9485
- totalMessages,
9486
- lastMessageSignature
9487
- };
9488
- }
9489
- return buildBoundedTailSync(messages, cursor);
9490
- }
9491
- }
9492
- const replaceFrom = Math.max(0, Math.min(knownMessageCount - 1, totalMessages));
9493
- return {
9494
- syncMode: replaceFrom === 0 ? "full" : "replace_tail",
9495
- replaceFrom,
9496
- messages: replaceFrom === 0 ? messages : messages.slice(replaceFrom),
9497
- totalMessages,
9498
- lastMessageSignature
9318
+ totalMessages
9499
9319
  };
9500
9320
  }
9501
9321
  function hasNonEmptyModalButtons(activeModal) {
@@ -9530,31 +9350,13 @@ function buildReadChatCommandResult(payload, args) {
9530
9350
  } catch (error48) {
9531
9351
  return { success: false, error: error48?.message || String(error48) };
9532
9352
  }
9533
- const messages = collapseReplayDuplicatesFromReadChat(normalizeReadChatMessages(validatedPayload));
9534
- const cursor = normalizeReadChatCursor(args);
9535
- if (!cursor.knownMessageCount && !cursor.lastMessageSignature && cursor.tailLimit > 0 && messages.length > cursor.tailLimit) {
9536
- const tailMessages = messages.slice(-cursor.tailLimit);
9537
- const lastMessageSignature = getChatMessageSignature(tailMessages[tailMessages.length - 1]);
9538
- return {
9539
- success: true,
9540
- ...validatedPayload,
9541
- messages: tailMessages,
9542
- syncMode: "full",
9543
- replaceFrom: 0,
9544
- totalMessages: messages.length,
9545
- lastMessageSignature,
9546
- ...debugReadChat ? { debugReadChat } : {}
9547
- };
9548
- }
9549
- const sync = computeReadChatSync(messages, cursor);
9353
+ const messages = normalizeReadChatMessages(validatedPayload);
9354
+ const sync = buildFullTail(messages, normalizeReadChatTailLimit(args));
9550
9355
  return {
9551
9356
  success: true,
9552
9357
  ...validatedPayload,
9553
9358
  messages: sync.messages,
9554
- syncMode: sync.syncMode,
9555
- replaceFrom: sync.replaceFrom,
9556
9359
  totalMessages: sync.totalMessages,
9557
- lastMessageSignature: sync.lastMessageSignature,
9558
9360
  ...debugReadChat ? { debugReadChat } : {}
9559
9361
  };
9560
9362
  }
@@ -9772,10 +9574,6 @@ async function handleGetChatDebugBundle(h, args) {
9772
9574
  status: readResult.status,
9773
9575
  title: readResult.title,
9774
9576
  totalMessages: readResult.totalMessages,
9775
- returnedMessages: Array.isArray(readResult.messages) ? readResult.messages.length : void 0,
9776
- syncMode: readResult.syncMode,
9777
- replaceFrom: readResult.replaceFrom,
9778
- lastMessageSignature: readResult.lastMessageSignature,
9779
9577
  providerSessionId: readResult.providerSessionId,
9780
9578
  transcriptAuthority: readResult.transcriptAuthority,
9781
9579
  coverage: readResult.coverage,
@@ -9885,22 +9683,13 @@ function toNonNegativeNumber(value) {
9885
9683
  return Number.isFinite(numeric) ? Math.max(0, numeric) : 0;
9886
9684
  }
9887
9685
  function getCliVisibleTranscriptCount(adapter) {
9888
- const adapterStatus = adapter?.getStatus?.() || {};
9889
- const adapterMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
9890
- let parsedRecord = null;
9891
- if (typeof adapter?.getScriptParsedStatus === "function") {
9892
- try {
9893
- const parsed = parseMaybeJson(adapter.getScriptParsedStatus());
9894
- parsedRecord = parsed && typeof parsed === "object" ? parsed : null;
9895
- } catch {
9896
- parsedRecord = null;
9897
- }
9686
+ if (typeof adapter?.getScriptParsedStatus !== "function") return 0;
9687
+ try {
9688
+ const parsed = parseMaybeJson(adapter.getScriptParsedStatus());
9689
+ return Array.isArray(parsed?.messages) ? parsed.messages.length : 0;
9690
+ } catch {
9691
+ return 0;
9898
9692
  }
9899
- const parsedMessages = Array.isArray(parsedRecord?.messages) ? parsedRecord.messages : [];
9900
- if (!parsedRecord) return adapterMessages.length;
9901
- const parsedIsProviderAuthoritative = parsedRecord.transcriptAuthority === "provider" || parsedRecord.coverage === "full";
9902
- const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && adapterMessages.length > 0 && adapterMessages.length > parsedMessages.length;
9903
- return shouldPreferAdapterMessages ? adapterMessages.length : parsedMessages.length;
9904
9693
  }
9905
9694
  async function getStableExtensionBaseline(h) {
9906
9695
  const first = await readExtensionChatState(h);
@@ -9962,52 +9751,46 @@ async function handleReadChat(h, args) {
9962
9751
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
9963
9752
  if (adapter) {
9964
9753
  _log(`${transport} adapter: ${adapter.cliType}`);
9754
+ if (typeof adapter.getScriptParsedStatus !== "function") {
9755
+ return { success: false, error: `${transport} adapter parseSession unavailable` };
9756
+ }
9965
9757
  let parsedStatus = null;
9966
- if (typeof adapter.getScriptParsedStatus === "function") {
9967
- try {
9968
- parsedStatus = parseMaybeJson(adapter.getScriptParsedStatus());
9969
- } catch (error48) {
9970
- return { success: false, error: error48?.message || String(error48) };
9971
- }
9758
+ try {
9759
+ parsedStatus = parseMaybeJson(adapter.getScriptParsedStatus());
9760
+ } catch (error48) {
9761
+ return { success: false, error: error48?.message || String(error48) };
9972
9762
  }
9973
9763
  const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
9974
- const adapterStatus = adapter.getStatus();
9975
- const parsedIsProviderAuthoritative = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.coverage === "full";
9976
- const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
9977
- const parsedShowsApproval = hasNonEmptyModalButtons(parsedRecord?.activeModal) && parsedRecord?.status === "waiting_approval";
9978
- const status = parsedRecord ? {
9979
- ...parsedRecord,
9980
- messages: shouldPreferAdapterMessages ? adapterStatus.messages : parsedRecord.messages,
9981
- status: parsedShowsApproval ? parsedRecord.status : adapterStatus.status !== "idle" ? adapterStatus.status : parsedRecord.status || adapterStatus.status,
9982
- activeModal: parsedRecord.activeModal || adapterStatus.activeModal
9983
- } : adapterStatus;
9984
- const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
9985
- const providerSessionId = typeof parsedRecord?.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
9986
- const transcriptAuthority = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
9987
- const coverage = parsedRecord?.coverage === "full" || parsedRecord?.coverage === "tail" || parsedRecord?.coverage === "current-turn" ? parsedRecord.coverage : void 0;
9988
- if (status) {
9989
- 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}`);
9990
- return buildReadChatCommandResult({
9991
- messages: status.messages || [],
9992
- status: status.status,
9993
- activeModal: status.activeModal,
9994
- debugReadChat: {
9995
- provider: adapter.cliType,
9996
- targetSessionId: String(args?.targetSessionId || ""),
9997
- adapterStatus: String(adapterStatus.status || ""),
9998
- parsedStatus: String(parsedRecord?.status || ""),
9999
- returnedStatus: String(status.status || ""),
10000
- shouldPreferAdapterMessages,
10001
- adapterMsgCount: Array.isArray(adapterStatus.messages) ? adapterStatus.messages.length : 0,
10002
- parsedMsgCount: Array.isArray(parsedRecord?.messages) ? parsedRecord.messages.length : 0,
10003
- returnedMsgCount: Array.isArray(status.messages) ? status.messages.length : 0
10004
- },
10005
- ...title ? { title } : {},
10006
- ...providerSessionId ? { providerSessionId } : {},
10007
- ...transcriptAuthority ? { transcriptAuthority } : {},
10008
- ...coverage ? { coverage } : {}
10009
- }, args);
10010
- }
9764
+ if (!parsedRecord || !Array.isArray(parsedRecord.messages)) {
9765
+ return { success: false, error: `${transport} parser did not return messages` };
9766
+ }
9767
+ const adapterStatus = typeof adapter.getStatus === "function" ? adapter.getStatus() : {};
9768
+ const title = typeof parsedRecord.title === "string" ? parsedRecord.title : void 0;
9769
+ const providerSessionId = typeof parsedRecord.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
9770
+ const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
9771
+ const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
9772
+ const activeModal = parsedRecord.activeModal ?? parsedRecord.modal ?? null;
9773
+ const returnedStatus = parsedRecord.status || "idle";
9774
+ 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}`);
9775
+ return buildReadChatCommandResult({
9776
+ messages: parsedRecord.messages,
9777
+ status: returnedStatus,
9778
+ activeModal,
9779
+ debugReadChat: {
9780
+ provider: adapter.cliType,
9781
+ targetSessionId: String(args?.targetSessionId || ""),
9782
+ adapterStatus: String(adapterStatus.status || ""),
9783
+ parsedStatus: String(parsedRecord.status || ""),
9784
+ returnedStatus: String(returnedStatus || ""),
9785
+ shouldPreferAdapterMessages: false,
9786
+ parsedMsgCount: parsedRecord.messages.length,
9787
+ returnedMsgCount: parsedRecord.messages.length
9788
+ },
9789
+ ...title ? { title } : {},
9790
+ ...providerSessionId ? { providerSessionId } : {},
9791
+ ...transcriptAuthority ? { transcriptAuthority } : {},
9792
+ ...coverage ? { coverage } : {}
9793
+ }, args);
10011
9794
  }
10012
9795
  return { success: false, error: `${transport} adapter not found` };
10013
9796
  }
@@ -10861,7 +10644,6 @@ var init_chat_commands = __esm({
10861
10644
  init_logger();
10862
10645
  init_debug_trace();
10863
10646
  init_chat_signatures();
10864
- init_chat_message_normalization();
10865
10647
  RECENT_SEND_WINDOW_MS = 1200;
10866
10648
  READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25e3;
10867
10649
  recentSendByTarget = /* @__PURE__ */ new Map();
@@ -14038,67 +13820,6 @@ function promptLikelyVisible(screenText, promptSnippet) {
14038
13820
  function normalizeScreenSnapshot(text) {
14039
13821
  return sanitizeTerminalText(String(text || "")).replace(/\s+/g, " ").trim();
14040
13822
  }
14041
- function shouldReflowComparableMessageLines(lines) {
14042
- 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));
14043
- }
14044
- function joinComparableMessageLines(lines) {
14045
- return lines.reduce((acc, line) => {
14046
- const next = String(line || "").trim();
14047
- if (!next) return acc;
14048
- if (!acc) return next;
14049
- if (/[,\d]$/.test(acc) && /^\d/.test(next)) {
14050
- return `${acc}${next}`;
14051
- }
14052
- if (/[A-Za-z]$/.test(acc) && /^\d/.test(next)) {
14053
- return `${acc}${next}`;
14054
- }
14055
- const fragmentMatch = acc.match(/([A-Za-z]{1,4})$/);
14056
- const fragment = fragmentMatch ? fragmentMatch[1].toLowerCase() : "";
14057
- if (/^[a-z]/.test(next) && fragment && !COMMON_COMPARABLE_WRAP_WORDS.has(fragment)) {
14058
- return `${acc}${next}`;
14059
- }
14060
- return `${acc} ${next}`;
14061
- }, "").replace(/\s+([,.;:!?])/g, "$1").replace(/(\d)\s+,/g, "$1,").replace(/\s+/g, " ").trim();
14062
- }
14063
- function normalizeComparableMessageContent(text) {
14064
- const lines = String(text || "").split(/\r\n|\n|\r/g).map((line) => line.trim()).filter(Boolean);
14065
- if (lines.length === 0) return "";
14066
- if (shouldReflowComparableMessageLines(lines)) {
14067
- return joinComparableMessageLines(lines);
14068
- }
14069
- return lines.join(" ").replace(/\s+/g, " ").trim();
14070
- }
14071
- function trimPromptEchoPrefix(text, promptText) {
14072
- const prompt2 = normalizeComparableMessageContent(String(promptText || ""));
14073
- if (!prompt2) return String(text || "");
14074
- const lines = String(text || "").split(/\r\n|\n|\r/g);
14075
- let dropCount = 0;
14076
- for (let index = 0; index < Math.min(lines.length, 6); index += 1) {
14077
- const fragment = normalizeComparableMessageContent(lines[index].replace(/^[.…]+\s*/, ""));
14078
- if (!fragment) {
14079
- if (dropCount === index) dropCount = index + 1;
14080
- continue;
14081
- }
14082
- const fragmentWordCount = fragment ? fragment.split(/\s+/).filter(Boolean).length : 0;
14083
- const canBePromptEcho = fragment.length >= 16 || fragmentWordCount >= 4;
14084
- if (canBePromptEcho && prompt2.includes(fragment)) {
14085
- dropCount = index + 1;
14086
- continue;
14087
- }
14088
- break;
14089
- }
14090
- return lines.slice(dropCount).join("\n").trim();
14091
- }
14092
- function getLastUserPromptText(messages) {
14093
- const items = Array.isArray(messages) ? messages : [];
14094
- for (let index = items.length - 1; index >= 0; index -= 1) {
14095
- const message = items[index];
14096
- if (message?.role === "user" && typeof message.content === "string" && message.content.trim()) {
14097
- return message.content;
14098
- }
14099
- }
14100
- return "";
14101
- }
14102
13823
  function parsePatternEntry(x) {
14103
13824
  if (x instanceof RegExp) return x;
14104
13825
  if (x && typeof x === "object" && typeof x.source === "string") {
@@ -14125,7 +13846,7 @@ function normalizeCliProviderForRuntime(raw) {
14125
13846
  }
14126
13847
  };
14127
13848
  }
14128
- var os12, path14, import_child_process4, buildCliSpawnEnv, COMMON_COMPARABLE_WRAP_WORDS;
13849
+ var os12, path14, import_child_process4, buildCliSpawnEnv;
14129
13850
  var init_provider_cli_shared = __esm({
14130
13851
  "../../oss/packages/daemon-core/src/cli-adapters/provider-cli-shared.ts"() {
14131
13852
  "use strict";
@@ -14134,32 +13855,6 @@ var init_provider_cli_shared = __esm({
14134
13855
  import_child_process4 = require("child_process");
14135
13856
  init_spawn_env();
14136
13857
  buildCliSpawnEnv = sanitizeSpawnEnv;
14137
- COMMON_COMPARABLE_WRAP_WORDS = /* @__PURE__ */ new Set([
14138
- "a",
14139
- "an",
14140
- "and",
14141
- "as",
14142
- "at",
14143
- "but",
14144
- "by",
14145
- "for",
14146
- "from",
14147
- "in",
14148
- "into",
14149
- "is",
14150
- "it",
14151
- "of",
14152
- "on",
14153
- "or",
14154
- "that",
14155
- "the",
14156
- "their",
14157
- "then",
14158
- "this",
14159
- "to",
14160
- "was",
14161
- "with"
14162
- ]);
14163
13858
  }
14164
13859
  });
14165
13860
 
@@ -14170,169 +13865,8 @@ function sliceFromOffset(text, start) {
14170
13865
  if (start >= text.length) return "";
14171
13866
  return text.slice(start);
14172
13867
  }
14173
- function hydrateCliParsedMessages(parsedMessages, options) {
14174
- const { committedMessages, scope, lastOutputAt } = options;
14175
- const referenceMessages = [...committedMessages];
14176
- const referenceComparables = new Array(referenceMessages.length);
14177
- const usedReferenceIndexes = /* @__PURE__ */ new Set();
14178
- const now = options.now ?? Date.now();
14179
- let exactReferenceIndexesByKey = null;
14180
- const exactReferenceCursorByKey = /* @__PURE__ */ new Map();
14181
- const hasFiniteTimestamp = (message) => typeof message?.timestamp === "number" && Number.isFinite(message.timestamp);
14182
- const getReferenceComparable = (index) => {
14183
- if (typeof referenceComparables[index] === "string") return referenceComparables[index] || "";
14184
- const comparable = normalizeComparableMessageContent(referenceMessages[index]?.content || "");
14185
- referenceComparables[index] = comparable;
14186
- return comparable;
14187
- };
14188
- const messagesShareStableIdentity = (parsed, reference) => {
14189
- if (!parsed || !reference) return false;
14190
- const parsedId = typeof parsed.id === "string" ? parsed.id.trim() : "";
14191
- const referenceId = typeof reference.id === "string" ? reference.id.trim() : "";
14192
- if (parsedId && referenceId && parsedId === referenceId) return true;
14193
- return typeof parsed.index === "number" && Number.isFinite(parsed.index) && typeof reference.index === "number" && Number.isFinite(reference.index) && parsed.index === reference.index;
14194
- };
14195
- const exactReferenceKey = (role, comparable) => `${role}\0${comparable}`;
14196
- const ensureExactReferenceIndex = () => {
14197
- if (exactReferenceIndexesByKey) return exactReferenceIndexesByKey;
14198
- const byKey = /* @__PURE__ */ new Map();
14199
- for (let i = 0; i < referenceMessages.length; i++) {
14200
- const candidate = referenceMessages[i];
14201
- if (!candidate || candidate.role !== "user" && candidate.role !== "assistant" || !hasFiniteTimestamp(candidate)) continue;
14202
- const comparable = getReferenceComparable(i);
14203
- if (!comparable) continue;
14204
- const key = exactReferenceKey(candidate.role, comparable);
14205
- const indexes = byKey.get(key);
14206
- if (indexes) {
14207
- indexes.push(i);
14208
- } else {
14209
- byKey.set(key, [i]);
14210
- }
14211
- }
14212
- exactReferenceIndexesByKey = byKey;
14213
- return byKey;
14214
- };
14215
- const takeExactReferenceTimestamp = (role, normalizedContent) => {
14216
- const key = exactReferenceKey(role, normalizedContent);
14217
- const indexes = ensureExactReferenceIndex().get(key);
14218
- if (!indexes) return void 0;
14219
- let cursor = exactReferenceCursorByKey.get(key) || 0;
14220
- while (cursor < indexes.length) {
14221
- const candidateIndex = indexes[cursor];
14222
- cursor += 1;
14223
- if (usedReferenceIndexes.has(candidateIndex)) continue;
14224
- const candidate = referenceMessages[candidateIndex];
14225
- if (!candidate || candidate.role !== role || !hasFiniteTimestamp(candidate)) continue;
14226
- usedReferenceIndexes.add(candidateIndex);
14227
- exactReferenceCursorByKey.set(key, cursor);
14228
- return candidate.timestamp;
14229
- }
14230
- exactReferenceCursorByKey.set(key, cursor);
14231
- return void 0;
14232
- };
14233
- const findReferenceTimestamp = (message, role, content, parsedIndex) => {
14234
- const sameIndex = referenceMessages[parsedIndex];
14235
- if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && hasFiniteTimestamp(sameIndex) && messagesShareStableIdentity(message, sameIndex)) {
14236
- usedReferenceIndexes.add(parsedIndex);
14237
- return sameIndex.timestamp;
14238
- }
14239
- const normalizedContent = normalizeComparableMessageContent(content);
14240
- if (!normalizedContent) return void 0;
14241
- if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && getReferenceComparable(parsedIndex) === normalizedContent && hasFiniteTimestamp(sameIndex)) {
14242
- usedReferenceIndexes.add(parsedIndex);
14243
- return sameIndex.timestamp;
14244
- }
14245
- const exactTimestamp = takeExactReferenceTimestamp(role, normalizedContent);
14246
- if (typeof exactTimestamp === "number") return exactTimestamp;
14247
- for (let i = 0; i < referenceMessages.length; i++) {
14248
- if (usedReferenceIndexes.has(i)) continue;
14249
- const candidate = referenceMessages[i];
14250
- if (!candidate || candidate.role !== role) continue;
14251
- const candidateContent = getReferenceComparable(i);
14252
- if (!candidateContent) continue;
14253
- const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
14254
- if (!fuzzyMatch) continue;
14255
- if (hasFiniteTimestamp(candidate)) {
14256
- usedReferenceIndexes.add(i);
14257
- return candidate.timestamp;
14258
- }
14259
- }
14260
- return void 0;
14261
- };
14262
- return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message, index) => {
14263
- const role = message.role;
14264
- const content = typeof message.content === "string" ? message.content : String(message.content || "");
14265
- const parsedTimestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0;
14266
- const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(message, role, content, index);
14267
- const fallbackTimestamp = role === "user" ? scope?.startedAt || now : lastOutputAt || scope?.startedAt || now;
14268
- const timestamp = referenceTimestamp ?? fallbackTimestamp;
14269
- return {
14270
- ...message,
14271
- role,
14272
- content,
14273
- timestamp,
14274
- receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp
14275
- };
14276
- });
14277
- }
14278
- function chooseMoreComparableCliMessage(left2, right2, leftComparable = normalizeComparableMessageContent(left2.content || ""), rightComparable = normalizeComparableMessageContent(right2.content || "")) {
14279
- if (leftComparable && leftComparable === rightComparable) {
14280
- const leftNewlines = String(left2.content || "").split(/\r\n|\n|\r/g).length - 1;
14281
- const rightNewlines = String(right2.content || "").split(/\r\n|\n|\r/g).length - 1;
14282
- return rightNewlines < leftNewlines ? right2 : left2;
14283
- }
14284
- return rightComparable.length > leftComparable.length ? right2 : left2;
14285
- }
14286
- function dedupeConsecutiveComparableCliMessages(messages) {
14287
- const deduped = [];
14288
- for (const message of messages) {
14289
- const current = {
14290
- ...message,
14291
- content: typeof message.content === "string" ? message.content : String(message.content || "")
14292
- };
14293
- const currentComparable = normalizeComparableMessageContent(current.content || "");
14294
- const previous = deduped[deduped.length - 1];
14295
- if (!previous) {
14296
- deduped.push({ message: current, comparable: currentComparable });
14297
- continue;
14298
- }
14299
- const sameRole = previous.message.role === current.role;
14300
- const sameKind = (previous.message.kind || "standard") === (current.kind || "standard");
14301
- const sameSender = (previous.message.senderName || "") === (current.senderName || "");
14302
- const comparableMatch = previous.comparable && previous.comparable === currentComparable;
14303
- if (sameRole && sameKind && sameSender && comparableMatch) {
14304
- const selected = chooseMoreComparableCliMessage(
14305
- previous.message,
14306
- current,
14307
- previous.comparable,
14308
- currentComparable
14309
- );
14310
- deduped[deduped.length - 1] = {
14311
- message: selected,
14312
- comparable: selected === current ? currentComparable : previous.comparable
14313
- };
14314
- continue;
14315
- }
14316
- deduped.push({ message: current, comparable: currentComparable });
14317
- }
14318
- return deduped.map((entry) => entry.message);
14319
- }
14320
- function normalizeCliParsedMessages(parsedMessages, options) {
14321
- return dedupeConsecutiveComparableCliMessages(hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
14322
- role: message.role,
14323
- content: message.content,
14324
- timestamp: message.timestamp,
14325
- receivedAt: message.receivedAt,
14326
- kind: message.kind,
14327
- id: message.id,
14328
- index: message.index,
14329
- providerUnitKey: message.providerUnitKey,
14330
- bubbleId: message.bubbleId,
14331
- bubbleState: message.bubbleState,
14332
- _turnKey: message._turnKey,
14333
- meta: message.meta,
14334
- senderName: message.senderName
14335
- })));
13868
+ function normalizeCliParsedMessages(parsedMessages, _options) {
13869
+ return Array.isArray(parsedMessages) ? parsedMessages : [];
14336
13870
  }
14337
13871
  function buildCliParseInput(options) {
14338
13872
  const {
@@ -14542,40 +14076,8 @@ var provider_cli_adapter_exports = {};
14542
14076
  __export(provider_cli_adapter_exports, {
14543
14077
  ProviderCliAdapter: () => ProviderCliAdapter,
14544
14078
  appendBoundedText: () => appendBoundedText,
14545
- normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime,
14546
- sanitizeCliStandardMessageContent: () => sanitizeCliStandardMessageContent,
14547
- trimLastAssistantEchoForCliMessages: () => trimLastAssistantEchoForCliMessages
14548
- });
14549
- function normalizeComparableTranscriptText(value) {
14550
- return sanitizeTerminalText(String(value || "")).replace(/\s+/g, " ").trim();
14551
- }
14552
- function hasVisibleInterruptPrompt(text) {
14553
- const interruptCopyPattern = /\bEnter\s+to\s+interrupt\b(?:\s*,?\s*Ctrl\s*(?:\+|-)?\s*C\s+to\s+cancel)?/i;
14554
- return sanitizeTerminalText(text || "").split(/\r?\n/g).some((line) => {
14555
- const trimmed = line.trim();
14556
- if (!interruptCopyPattern.test(trimmed)) return false;
14557
- return /^(?:[^A-Za-z0-9\s]{1,8}\s+)?[❯›>]\s+/.test(trimmed);
14558
- });
14559
- }
14560
- function parsedTranscriptIsRicherThanCommitted(parsedMessages, committedMessages) {
14561
- if (!Array.isArray(parsedMessages) || !Array.isArray(committedMessages)) return false;
14562
- if (parsedMessages.length > committedMessages.length) return true;
14563
- if (parsedMessages.length !== committedMessages.length) return false;
14564
- for (let index = 0; index < parsedMessages.length; index += 1) {
14565
- const parsed = parsedMessages[index];
14566
- const committed = committedMessages[index];
14567
- if (!parsed || !committed) return false;
14568
- if ((parsed.role || "") !== (committed.role || "")) return false;
14569
- if (parsed.id && committed.id && String(parsed.id) !== String(committed.id)) return false;
14570
- if (typeof parsed.index === "number" && typeof committed.index === "number" && parsed.index !== committed.index) return false;
14571
- const parsedText = normalizeComparableTranscriptText(parsed.content);
14572
- const committedText = normalizeComparableTranscriptText(committed.content);
14573
- if (!parsedText || !committedText || parsedText === committedText) continue;
14574
- if (parsedText.length > committedText.length && parsedText.startsWith(committedText)) return true;
14575
- return false;
14576
- }
14577
- return false;
14578
- }
14079
+ normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
14080
+ });
14579
14081
  function appendBoundedText(current, chunk, maxChars) {
14580
14082
  if (!chunk) return current.length <= maxChars ? current : current.slice(-maxChars);
14581
14083
  if (maxChars <= 0) return "";
@@ -14584,76 +14086,7 @@ function appendBoundedText(current, chunk, maxChars) {
14584
14086
  if (current.length <= keepFromCurrent) return current + chunk;
14585
14087
  return current.slice(-keepFromCurrent) + chunk;
14586
14088
  }
14587
- function isLikelyCommittedActivityPrefixContinuation(line) {
14588
- const trimmed = String(line || "").trim();
14589
- if (!trimmed) return false;
14590
- if (COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(trimmed)) return false;
14591
- if (/\s/.test(trimmed)) return false;
14592
- if (/[가-힣]/.test(trimmed)) return false;
14593
- if (trimmed.length > 96) return false;
14594
- return /^[A-Za-z0-9_./:@+%=-]+$/.test(trimmed);
14595
- }
14596
- function parseCommittedActivityPrefixBlock(lines, index) {
14597
- const first = String(lines[index] || "").trim();
14598
- if (!COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(first)) return null;
14599
- const parts = [first];
14600
- let nextIndex = index + 1;
14601
- while (nextIndex < lines.length && isLikelyCommittedActivityPrefixContinuation(lines[nextIndex])) {
14602
- parts.push(String(lines[nextIndex] || "").trim());
14603
- nextIndex += 1;
14604
- }
14605
- return { label: parts.join(""), nextIndex };
14606
- }
14607
- function sanitizeCliStandardMessageContent(content) {
14608
- const source = String(content || "").trim();
14609
- if (!source) return "";
14610
- const lines = source.split(/\r?\n/);
14611
- if (lines.length < 4) return source;
14612
- const counts = /* @__PURE__ */ new Map();
14613
- for (let index = 0; index < lines.length; index += 1) {
14614
- const block = parseCommittedActivityPrefixBlock(lines, index);
14615
- if (!block) continue;
14616
- counts.set(block.label, (counts.get(block.label) || 0) + 1);
14617
- index = block.nextIndex - 1;
14618
- }
14619
- const repeatedLabels = new Set(
14620
- Array.from(counts.entries()).filter(([, count]) => count >= 3).map(([label]) => label)
14621
- );
14622
- if (repeatedLabels.size === 0) return source;
14623
- const stripped = [];
14624
- let removed = 0;
14625
- for (let index = 0; index < lines.length; index += 1) {
14626
- const block = parseCommittedActivityPrefixBlock(lines, index);
14627
- if (block && repeatedLabels.has(block.label)) {
14628
- removed += 1;
14629
- index = block.nextIndex - 1;
14630
- continue;
14631
- }
14632
- stripped.push(lines[index]);
14633
- }
14634
- const next = stripped.join("\n").replace(/\n{3,}/g, "\n\n").trim();
14635
- return removed >= 3 && next.length >= 80 ? next : source;
14636
- }
14637
- function sanitizeCommittedMessageForDisplay(message) {
14638
- if (!message || message.role !== "assistant" || (message.kind || "standard") !== "standard") return message;
14639
- const content = sanitizeCliStandardMessageContent(message.content);
14640
- if (content === message.content) return message;
14641
- return { ...message, content };
14642
- }
14643
- function trimLastAssistantEchoForCliMessages(messages, prompt2) {
14644
- if (!prompt2) return;
14645
- for (let index = messages.length - 1; index >= 0; index -= 1) {
14646
- const message = messages[index];
14647
- if (!message || message.role !== "assistant" || typeof message.content !== "string") continue;
14648
- if ((message.kind || "standard") !== "standard") continue;
14649
- message.content = trimPromptEchoPrefix(message.content, prompt2);
14650
- if (!message.content.trim()) {
14651
- messages.splice(index, 1);
14652
- }
14653
- return;
14654
- }
14655
- }
14656
- var os14, COMMITTED_ACTIVITY_PREFIX_BLOCK_RE, ProviderCliAdapter;
14089
+ var os14, ProviderCliAdapter;
14657
14090
  var init_provider_cli_adapter = __esm({
14658
14091
  "../../oss/packages/daemon-core/src/cli-adapters/provider-cli-adapter.ts"() {
14659
14092
  "use strict";
@@ -14663,13 +14096,10 @@ var init_provider_cli_adapter = __esm({
14663
14096
  init_terminal_screen();
14664
14097
  init_pty_transport();
14665
14098
  init_provider_cli_shared();
14666
- init_chat_message_normalization();
14667
- init_read_chat_contract();
14668
14099
  init_provider_cli_parse();
14669
14100
  init_provider_cli_config();
14670
14101
  init_provider_cli_runtime();
14671
14102
  init_provider_cli_shared();
14672
- COMMITTED_ACTIVITY_PREFIX_BLOCK_RE = /^(?:📖|💻|🔎|📚|📋|✏️|📝|🔧|🛠️|⚙️)\s+(.+)$/;
14673
14103
  ProviderCliAdapter = class _ProviderCliAdapter {
14674
14104
  constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
14675
14105
  this.extraArgs = extraArgs;
@@ -14712,11 +14142,6 @@ var init_provider_cli_adapter = __esm({
14712
14142
  provider;
14713
14143
  ptyProcess = null;
14714
14144
  transportFactory;
14715
- messages = [];
14716
- committedMessages = [];
14717
- structuredMessages = [];
14718
- committedMessagesActivitySignature = "";
14719
- committedMessagesChangedAt = 0;
14720
14145
  currentStatus = "starting";
14721
14146
  onStatusChange = null;
14722
14147
  responseBuffer = "";
@@ -14796,11 +14221,8 @@ var init_provider_cli_adapter = __esm({
14796
14221
  traceSeq = 0;
14797
14222
  traceSessionId = "";
14798
14223
  parsedStatusCache = null;
14799
- lastStatusHotPathParseAt = Number.NEGATIVE_INFINITY;
14800
- static STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS = 1e3;
14801
14224
  static SCREEN_SNAPSHOT_MIN_INTERVAL_MS = 250;
14802
14225
  static MAX_TRACE_ENTRIES = 250;
14803
- static PARSE_MESSAGE_TAIL_LIMIT = 100;
14804
14226
  providerResolutionMeta;
14805
14227
  static FINISH_RETRY_DELAY_MS = 300;
14806
14228
  static MAX_FINISH_RETRIES = 2;
@@ -14821,35 +14243,6 @@ var init_provider_cli_adapter = __esm({
14821
14243
  recordBoundedAppendDrop(previousLength, appendedLength, nextLength) {
14822
14244
  return Math.max(0, previousLength + appendedLength - nextLength);
14823
14245
  }
14824
- buildCommittedMessagesActivitySignature() {
14825
- const last = this.committedMessages[this.committedMessages.length - 1];
14826
- return [
14827
- String(this.committedMessages.length),
14828
- String(last?.role || ""),
14829
- String(last?.kind || ""),
14830
- String(last?.senderName || ""),
14831
- String(last?.timestamp || ""),
14832
- String(last?.receivedAt || ""),
14833
- normalizeComparableMessageContent(last?.content || "").slice(-240)
14834
- ].join("|");
14835
- }
14836
- syncMessageViews() {
14837
- const signature = this.buildCommittedMessagesActivitySignature();
14838
- if (signature !== this.committedMessagesActivitySignature) {
14839
- this.committedMessagesActivitySignature = signature;
14840
- this.committedMessagesChangedAt = Date.now();
14841
- }
14842
- this.messages = [...this.committedMessages];
14843
- this.structuredMessages = [...this.committedMessages];
14844
- }
14845
- getLastCommittedMessageActivityAt() {
14846
- const last = this.committedMessages[this.committedMessages.length - 1];
14847
- const messageTime = Math.max(
14848
- typeof last?.receivedAt === "number" && Number.isFinite(last.receivedAt) ? last.receivedAt : 0,
14849
- typeof last?.timestamp === "number" && Number.isFinite(last.timestamp) ? last.timestamp : 0
14850
- );
14851
- return Math.max(messageTime, this.committedMessagesChangedAt || 0);
14852
- }
14853
14246
  readTerminalScreenText(now = Date.now()) {
14854
14247
  const screenText = this.terminalScreen.getText() || "";
14855
14248
  this.lastScreenText = screenText;
@@ -14869,7 +14262,7 @@ var init_provider_cli_adapter = __esm({
14869
14262
  }
14870
14263
  getFreshParsedStatusCache() {
14871
14264
  const cached2 = this.parsedStatusCache;
14872
- 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) {
14265
+ 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) {
14873
14266
  return cached2.result;
14874
14267
  }
14875
14268
  return null;
@@ -14880,45 +14273,6 @@ var init_provider_cli_adapter = __esm({
14880
14273
  shouldUseFullProviderTranscriptContext() {
14881
14274
  return this.providerOwnsTranscript() && this.provider.transcriptContext === "full";
14882
14275
  }
14883
- selectParseBaseMessages(baseMessages) {
14884
- if (this.shouldUseFullProviderTranscriptContext()) return baseMessages;
14885
- if (baseMessages.length <= _ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
14886
- return baseMessages.slice(-_ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
14887
- }
14888
- messagesShareStableIdentity(left2, right2) {
14889
- if (left2 === right2) return true;
14890
- if (!left2 || !right2) return false;
14891
- if ((left2.role || "") !== (right2.role || "")) return false;
14892
- if (left2.id && right2.id && String(left2.id) === String(right2.id)) return true;
14893
- if (typeof left2.index === "number" && typeof right2.index === "number" && left2.index === right2.index) return true;
14894
- return false;
14895
- }
14896
- messagesComparable(left2, right2) {
14897
- if (this.messagesShareStableIdentity(left2, right2)) return true;
14898
- if (!left2 || !right2) return false;
14899
- if ((left2.role || "") !== (right2.role || "")) return false;
14900
- const leftText = normalizeComparableTranscriptText(left2.content);
14901
- const rightText = normalizeComparableTranscriptText(right2.content);
14902
- return !!leftText && leftText === rightText;
14903
- }
14904
- stitchParsedMessagesWithCommittedBase(parsedMessages, fullBaseMessages, parseBaseMessages) {
14905
- if (!Array.isArray(parsedMessages) || parsedMessages.length === 0) return parsedMessages;
14906
- if (fullBaseMessages.length <= parseBaseMessages.length) return parsedMessages;
14907
- const parsedFirst = parsedMessages[0];
14908
- const fullFirst = fullBaseMessages[0];
14909
- if (parsedMessages.length >= fullBaseMessages.length && this.messagesComparable(parsedFirst, fullFirst)) {
14910
- return parsedMessages;
14911
- }
14912
- const tailFirst = parseBaseMessages[0];
14913
- if (tailFirst && this.messagesComparable(parsedFirst, tailFirst)) {
14914
- const prefixLength = fullBaseMessages.length - parseBaseMessages.length;
14915
- const prefix = fullBaseMessages.slice(0, prefixLength);
14916
- const shouldSanitizePrefix = !!this.currentTurnScope || this.currentStatus !== "idle" || !!this.activeModal;
14917
- const nextPrefix = shouldSanitizePrefix ? prefix.map((message) => sanitizeCommittedMessageForDisplay(message)) : prefix;
14918
- return [...nextPrefix, ...parsedMessages];
14919
- }
14920
- return [...fullBaseMessages, ...parsedMessages];
14921
- }
14922
14276
  getIdleFinishConfirmMs() {
14923
14277
  return this.timeouts.idleFinishConfirm;
14924
14278
  }
@@ -15371,9 +14725,6 @@ var init_provider_cli_adapter = __esm({
15371
14725
  `[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(summarizeCliTraceText(finalScreenText, 240)).slice(0, 280)}`
15372
14726
  );
15373
14727
  }
15374
- trimLastAssistantEcho(messages, prompt2) {
15375
- trimLastAssistantEchoForCliMessages(messages, prompt2);
15376
- }
15377
14728
  clearAllTimers() {
15378
14729
  if (this.responseTimeout) {
15379
14730
  clearTimeout(this.responseTimeout);
@@ -15469,10 +14820,10 @@ var init_provider_cli_adapter = __esm({
15469
14820
  }
15470
14821
  const session = this.runParseSession();
15471
14822
  if (!session) return;
15472
- const { status, messages, modal, parsedStatus } = session;
14823
+ const { status, messages, parsedStatus } = session;
14824
+ const modal = session.activeModal ?? session.modal ?? null;
15473
14825
  const parsedMessages = normalizeCliParsedMessages(messages, {
15474
- committedMessages: this.committedMessages,
15475
- scope: this.currentTurnScope,
14826
+ scope: null,
15476
14827
  lastOutputAt: this.lastOutputAt
15477
14828
  });
15478
14829
  if (this.maybeCommitVisibleIdleTranscript(session, parsedMessages)) return;
@@ -15652,7 +15003,7 @@ var init_provider_cli_adapter = __esm({
15652
15003
  const effectiveScreenText = screenText || this.accumulatedBuffer;
15653
15004
  const noActiveTurn = !this.currentTurnScope;
15654
15005
  const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(effectiveScreenText);
15655
- const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant && parsedMessages.length > this.committedMessages.length;
15006
+ const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant;
15656
15007
  if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
15657
15008
  return;
15658
15009
  }
@@ -15809,10 +15160,7 @@ var init_provider_cli_adapter = __esm({
15809
15160
  }
15810
15161
  const visibleAssistant = [...parsedMessages].reverse().find((m) => m.role === "assistant" && m.content.trim());
15811
15162
  if (!visibleAssistant) return false;
15812
- this.committedMessages = parsedMessages;
15813
- this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
15814
15163
  this.clearAllTimers();
15815
- this.syncMessageViews();
15816
15164
  this.responseBuffer = "";
15817
15165
  this.isWaitingForResponse = false;
15818
15166
  this.responseSettleIgnoreUntil = 0;
@@ -15824,37 +15172,34 @@ var init_provider_cli_adapter = __esm({
15824
15172
  this.setStatus("idle", "script_idle_commit");
15825
15173
  this.onStatusChange?.();
15826
15174
  this.recordTrace("script_idle_commit", {
15827
- messageCount: this.committedMessages.length,
15175
+ messageCount: parsedMessages.length,
15828
15176
  lastAssistant: summarizeCliTraceText(visibleAssistant.content, 320)
15829
15177
  });
15830
15178
  return true;
15831
15179
  }
15832
15180
  commitCurrentTranscript() {
15833
15181
  const parsed = this.parseCurrentTranscript(
15834
- this.committedMessages,
15182
+ [],
15835
15183
  this.responseBuffer,
15836
15184
  this.currentTurnScope
15837
15185
  );
15838
15186
  if (parsed && Array.isArray(parsed.messages)) {
15839
- this.committedMessages = normalizeCliParsedMessages(parsed.messages, {
15840
- committedMessages: this.committedMessages,
15841
- scope: this.currentTurnScope,
15187
+ const parsedMessages = normalizeCliParsedMessages(parsed.messages, {
15188
+ scope: null,
15842
15189
  lastOutputAt: this.lastOutputAt
15843
15190
  });
15844
- this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
15845
- this.syncMessageViews();
15846
- const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
15191
+ const lastAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
15847
15192
  if (this.currentTurnScope) {
15848
15193
  LOG.info(
15849
15194
  "CLI",
15850
- `[${this.cliType}] commitCurrentTranscript committedMessages=${this.committedMessages.length} finalLastAssistant=${JSON.stringify(summarizeCliTraceText(lastAssistant?.content || "", 220)).slice(0, 260)}`
15195
+ `[${this.cliType}] commitCurrentTranscript parserMessages=${parsedMessages.length} finalLastAssistant=${JSON.stringify(summarizeCliTraceText(lastAssistant?.content || "", 220)).slice(0, 260)}`
15851
15196
  );
15852
15197
  }
15853
15198
  this.recordTrace("commit_transcript", {
15854
15199
  parsedStatus: parsed.status || null,
15855
- messageCount: this.committedMessages.length,
15200
+ messageCount: parsedMessages.length,
15856
15201
  lastAssistant: lastAssistant ? summarizeCliTraceText(lastAssistant.content, 320) : "",
15857
- messages: summarizeCliTraceMessages(this.committedMessages),
15202
+ messages: summarizeCliTraceMessages(parsedMessages),
15858
15203
  ...buildCliTraceParseSnapshot({
15859
15204
  accumulatedBuffer: this.accumulatedBuffer,
15860
15205
  accumulatedRawBuffer: this.accumulatedRawBuffer,
@@ -15888,63 +15233,31 @@ var init_provider_cli_adapter = __esm({
15888
15233
  }
15889
15234
  // ─── Script Execution ──────────────────────────
15890
15235
  runParseSession() {
15891
- if (typeof this.cliScripts?.parseSession === "function") {
15892
- try {
15893
- const screenText = this.terminalScreen.getText();
15894
- const tail = this.recentOutputBuffer.slice(-500);
15895
- const parseBaseMessages = this.selectParseBaseMessages(this.committedMessages);
15896
- const input = buildCliParseInput({
15897
- accumulatedBuffer: this.accumulatedBuffer,
15898
- accumulatedRawBuffer: this.accumulatedRawBuffer,
15899
- recentOutputBuffer: this.recentOutputBuffer,
15900
- terminalScreenText: screenText,
15901
- baseMessages: parseBaseMessages,
15902
- partialResponse: this.responseBuffer,
15903
- isWaitingForResponse: this.isWaitingForResponse,
15904
- scope: this.currentTurnScope,
15905
- runtimeSettings: this.runtimeSettings
15906
- });
15907
- const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
15908
- if (session && typeof session === "object" && Array.isArray(session.messages)) {
15909
- session.messages = this.stitchParsedMessagesWithCommittedBase(
15910
- session.messages,
15911
- this.committedMessages,
15912
- parseBaseMessages
15913
- );
15914
- }
15915
- this.parseErrorMessage = null;
15916
- return session && typeof session === "object" ? session : null;
15917
- } catch (e) {
15918
- const message = e?.message || String(e);
15919
- this.parseErrorMessage = message;
15920
- LOG.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
15921
- return null;
15922
- }
15236
+ if (typeof this.cliScripts?.parseSession !== "function") {
15237
+ this.parseErrorMessage = `${this.cliType} parseSession unavailable`;
15238
+ return null;
15923
15239
  }
15924
- if (!this.cliScripts?.detectStatus && !this.cliScripts?.parseOutput) return null;
15925
15240
  try {
15926
- const tail = this.settledBuffer;
15927
- const parsedTranscript = this.parseCurrentTranscript(
15928
- this.committedMessages,
15929
- this.responseBuffer,
15930
- this.currentTurnScope
15931
- );
15932
- const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((b) => typeof b === "string" && b.trim()) ? parsedTranscript.activeModal : null;
15933
- const approval = this.runParseApproval(tail);
15934
- const modal = approval || parsedModal;
15935
- const rawStatus = this.runDetectStatus(tail);
15936
- const parsedStatus = typeof parsedTranscript?.status === "string" ? parsedTranscript.status : null;
15937
- const effectiveStatus = parsedStatus === "waiting_approval" && modal ? "waiting_approval" : rawStatus || parsedStatus || "idle";
15938
- return {
15939
- status: effectiveStatus,
15940
- messages: Array.isArray(parsedTranscript?.messages) ? parsedTranscript.messages : [],
15941
- modal,
15942
- parsedStatus
15943
- };
15241
+ const screenText = this.terminalScreen.getText();
15242
+ const tail = this.recentOutputBuffer.slice(-500);
15243
+ const input = buildCliParseInput({
15244
+ accumulatedBuffer: this.accumulatedBuffer,
15245
+ accumulatedRawBuffer: this.accumulatedRawBuffer,
15246
+ recentOutputBuffer: this.recentOutputBuffer,
15247
+ terminalScreenText: screenText,
15248
+ baseMessages: [],
15249
+ partialResponse: this.responseBuffer,
15250
+ isWaitingForResponse: this.isWaitingForResponse,
15251
+ scope: this.currentTurnScope,
15252
+ runtimeSettings: this.runtimeSettings
15253
+ });
15254
+ const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
15255
+ this.parseErrorMessage = null;
15256
+ return session && typeof session === "object" ? session : null;
15944
15257
  } catch (e) {
15945
15258
  const message = e?.message || String(e);
15946
15259
  this.parseErrorMessage = message;
15947
- LOG.warn("CLI", `[${this.cliType}] parseSession fallback error: ${message}`);
15260
+ LOG.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
15948
15261
  return null;
15949
15262
  }
15950
15263
  }
@@ -15994,45 +15307,14 @@ var init_provider_cli_adapter = __esm({
15994
15307
  if (this.isWaitingForResponse && this.currentTurnScope && this.currentStatus !== "stopped") return "generating";
15995
15308
  return this.currentStatus;
15996
15309
  }
15997
- suppressStaleParsedApproval(parsed, recentBuffer, screenText) {
15998
- const actionableParsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
15999
- if (!parsed || parsed?.status !== "waiting_approval" || !actionableParsedModal) {
16000
- return parsed;
16001
- }
16002
- const inApprovalCooldown = this.lastApprovalResolvedAt > 0 && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
16003
- if (!inApprovalCooldown) {
16004
- return parsed;
16005
- }
16006
- const visibleModal = this.runParseApproval(recentBuffer);
16007
- if (visibleModal) {
16008
- return parsed;
16009
- }
16010
- const detectedStatus = this.runDetectStatus(recentBuffer);
16011
- const resolvedStatus = detectedStatus && detectedStatus !== "waiting_approval" ? detectedStatus : this.isWaitingForResponse || this.currentTurnScope ? "generating" : this.currentStatus === "waiting_approval" ? "idle" : this.currentStatus;
16012
- return {
16013
- ...parsed,
16014
- status: resolvedStatus,
16015
- activeModal: null
16016
- };
16017
- }
16018
15310
  // ─── Public API (CliAdapter) ───────────────────
16019
15311
  getStatus(options = {}) {
16020
15312
  const allowParse = options.allowParse !== false;
16021
15313
  const startupModal = allowParse && this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
16022
15314
  let effectiveStatus = this.projectEffectiveStatus(startupModal);
16023
15315
  let effectiveModal = startupModal || this.activeModal;
16024
- if (allowParse && !startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
16025
- let parsed = this.getFreshParsedStatusCache();
16026
- if (!parsed && effectiveStatus !== "idle") {
16027
- const now = Date.now();
16028
- if (now - this.lastStatusHotPathParseAt >= _ProviderCliAdapter.STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS) {
16029
- this.lastStatusHotPathParseAt = now;
16030
- try {
16031
- parsed = this.getScriptParsedStatus();
16032
- } catch {
16033
- }
16034
- }
16035
- }
15316
+ if (allowParse && !startupModal && !effectiveModal) {
15317
+ const parsed = this.getFreshParsedStatusCache();
16036
15318
  const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
16037
15319
  if (parsed?.status === "waiting_approval" && parsedModal) {
16038
15320
  effectiveStatus = "waiting_approval";
@@ -16042,7 +15324,7 @@ var init_provider_cli_adapter = __esm({
16042
15324
  const bufferState = this.getBufferState();
16043
15325
  return {
16044
15326
  status: effectiveStatus,
16045
- messages: [...this.committedMessages],
15327
+ messages: [],
16046
15328
  workingDir: this.workingDir,
16047
15329
  activeModal: effectiveModal,
16048
15330
  errorMessage: this.parseErrorMessage || void 0,
@@ -16050,98 +15332,6 @@ var init_provider_cli_adapter = __esm({
16050
15332
  ...bufferState ? { bufferState } : {}
16051
15333
  };
16052
15334
  }
16053
- seedCommittedMessages(messages) {
16054
- const normalized = (Array.isArray(messages) ? messages : []).filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
16055
- role: message.role,
16056
- content: typeof message.content === "string" ? message.content : String(message.content || ""),
16057
- timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0,
16058
- receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : void 0,
16059
- kind: typeof message.kind === "string" ? message.kind : void 0,
16060
- id: typeof message.id === "string" ? message.id : void 0,
16061
- index: typeof message.index === "number" ? message.index : void 0,
16062
- providerUnitKey: typeof message.providerUnitKey === "string" ? message.providerUnitKey : void 0,
16063
- bubbleId: typeof message.bubbleId === "string" ? message.bubbleId : void 0,
16064
- bubbleState: typeof message.bubbleState === "string" ? message.bubbleState : void 0,
16065
- _turnKey: typeof message._turnKey === "string" ? message._turnKey : void 0,
16066
- meta: message.meta && typeof message.meta === "object" ? { ...message.meta } : void 0,
16067
- senderName: typeof message.senderName === "string" ? message.senderName : void 0
16068
- }));
16069
- this.committedMessages = normalized;
16070
- this.syncMessageViews();
16071
- }
16072
- getSharedCommittedPrefixLength(parsedMessages) {
16073
- const committedMessages = this.committedMessages;
16074
- const max = Math.min(parsedMessages.length, committedMessages.length);
16075
- let index = 0;
16076
- while (index < max && this.messagesShareStableIdentity(parsedMessages[index], committedMessages[index])) {
16077
- index += 1;
16078
- }
16079
- return index;
16080
- }
16081
- hydrateCommittedPrefixForParsedStatus(parsedMessages) {
16082
- const sharedPrefixLength = this.getSharedCommittedPrefixLength(parsedMessages);
16083
- if (sharedPrefixLength !== this.committedMessages.length) return null;
16084
- const committedHydratedMessages = this.committedMessages.map((message, index) => {
16085
- const timestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : this.lastOutputAt || this.currentTurnScope?.startedAt || Date.now();
16086
- const contentValue = message.content;
16087
- return {
16088
- role: message.role,
16089
- content: typeof contentValue === "string" ? contentValue : String(contentValue || ""),
16090
- timestamp,
16091
- receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp,
16092
- kind: message.kind,
16093
- id: message.id || `msg_${index}`,
16094
- index: typeof message.index === "number" ? message.index : index,
16095
- providerUnitKey: message.providerUnitKey,
16096
- bubbleId: message.bubbleId,
16097
- bubbleState: message.bubbleState,
16098
- _turnKey: message._turnKey,
16099
- meta: message.meta,
16100
- senderName: message.senderName
16101
- };
16102
- });
16103
- const extraMessages = parsedMessages.slice(sharedPrefixLength);
16104
- if (extraMessages.length === 0) return committedHydratedMessages;
16105
- const extraHydratedMessages = hydrateCliParsedMessages(extraMessages, {
16106
- committedMessages: [],
16107
- scope: this.currentTurnScope,
16108
- lastOutputAt: this.lastOutputAt
16109
- }).map((message, offset) => ({
16110
- ...message,
16111
- id: message.id || `msg_${sharedPrefixLength + offset}`,
16112
- index: typeof message.index === "number" ? message.index : sharedPrefixLength + offset
16113
- }));
16114
- return [...committedHydratedMessages, ...extraHydratedMessages];
16115
- }
16116
- hydrateParsedMessagesForStatus(parsedMessages) {
16117
- return this.hydrateCommittedPrefixForParsedStatus(parsedMessages) || hydrateCliParsedMessages(parsedMessages, {
16118
- committedMessages: this.committedMessages,
16119
- scope: this.currentTurnScope,
16120
- lastOutputAt: this.lastOutputAt
16121
- });
16122
- }
16123
- buildCommittedChatMessages() {
16124
- return this.committedMessages.map((message, index) => {
16125
- const rawContentValue = message.content;
16126
- const rawContent = typeof rawContentValue === "string" ? rawContentValue : String(rawContentValue || "");
16127
- const content = message.role === "assistant" && (message.kind || "standard") === "standard" ? sanitizeCliStandardMessageContent(rawContent) : rawContent;
16128
- return buildChatMessage({
16129
- role: message.role,
16130
- content,
16131
- timestamp: message.timestamp,
16132
- kind: message.kind,
16133
- meta: message.meta,
16134
- senderName: message.senderName,
16135
- id: message.id || `msg_${index}`,
16136
- index: typeof message.index === "number" ? message.index : index,
16137
- providerUnitKey: message.providerUnitKey,
16138
- bubbleId: message.bubbleId,
16139
- bubbleState: message.bubbleState,
16140
- _turnKey: message._turnKey,
16141
- receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
16142
- });
16143
- });
16144
- }
16145
15335
  /**
16146
15336
  * Script-based full parse — returns ReadChatResult.
16147
15337
  * Called by command handler / dashboard for rich content rendering.
@@ -16149,125 +15339,30 @@ var init_provider_cli_adapter = __esm({
16149
15339
  getScriptParsedStatus() {
16150
15340
  const screenText = this.readTerminalScreenText();
16151
15341
  const cached2 = this.parsedStatusCache;
16152
- 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) {
15342
+ 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) {
16153
15343
  return cached2.result;
16154
15344
  }
16155
- const parsed = this.parseCurrentTranscript(
16156
- this.committedMessages,
16157
- this.responseBuffer,
16158
- this.currentTurnScope,
16159
- screenText
16160
- );
16161
- const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
16162
- if (parsedModal && parsed?.status === "waiting_approval") {
16163
- this.activeModal = parsedModal;
16164
- this.isWaitingForResponse = true;
16165
- if (this.currentStatus !== "waiting_approval") {
16166
- this.setStatus("waiting_approval", "parsed_waiting_approval");
16167
- this.onStatusChange?.();
16168
- }
15345
+ const parsed = this.runParseSession();
15346
+ if (!parsed || !Array.isArray(parsed.messages)) {
15347
+ throw new Error(this.parseErrorMessage || `${this.cliType} parseSession did not return messages`);
16169
15348
  }
16170
- if (parsed && Array.isArray(parsed.messages) && this.provider.allowInputDuringGeneration === true) {
16171
- const hydratedForCommit = normalizeCliParsedMessages(parsed.messages, {
16172
- committedMessages: this.committedMessages,
16173
- scope: this.currentTurnScope,
15349
+ const activeModal = parsed.activeModal ?? parsed.modal ?? null;
15350
+ const bufferState = this.getBufferState();
15351
+ const result = {
15352
+ id: parsed.id || "cli_session",
15353
+ status: parsed.status || this.currentStatus,
15354
+ title: parsed.title || this.cliName,
15355
+ messages: normalizeCliParsedMessages(parsed.messages, {
15356
+ scope: null,
16174
15357
  lastOutputAt: this.lastOutputAt
16175
- });
16176
- const fakeSession = {
16177
- status: parsed.status || "idle",
16178
- messages: parsed.messages,
16179
- modal: parsedModal,
16180
- parsedStatus: parsed.status || null
16181
- };
16182
- if (this.maybeCommitVisibleIdleTranscript(fakeSession, hydratedForCommit)) {
16183
- return this.getScriptParsedStatus();
16184
- }
16185
- }
16186
- const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
16187
- let result;
16188
- if (parsed && Array.isArray(parsed.messages)) {
16189
- const parsedHydratedMessages = this.hydrateParsedMessagesForStatus(parsed.messages);
16190
- const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === "assistant" && typeof message.content === "string" && message.content.trim());
16191
- 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");
16192
- if (shouldAdoptParsedIdleReplay) {
16193
- this.committedMessages = this.getSharedCommittedPrefixLength(parsed.messages) === this.committedMessages.length ? parsedHydratedMessages.map((message) => ({
16194
- role: message.role,
16195
- content: typeof message.content === "string" ? message.content : String(message.content || ""),
16196
- timestamp: message.timestamp,
16197
- receivedAt: message.receivedAt,
16198
- kind: message.kind,
16199
- id: message.id,
16200
- index: message.index,
16201
- meta: message.meta,
16202
- senderName: message.senderName
16203
- })) : normalizeCliParsedMessages(parsed.messages, {
16204
- committedMessages: this.committedMessages,
16205
- scope: this.currentTurnScope,
16206
- lastOutputAt: this.lastOutputAt
16207
- });
16208
- this.syncMessageViews();
16209
- if (this.currentStatus !== "idle" || this.isWaitingForResponse) {
16210
- this.responseBuffer = "";
16211
- this.isWaitingForResponse = false;
16212
- this.responseSettleIgnoreUntil = 0;
16213
- this.submitRetryUsed = false;
16214
- this.submitRetryPromptSnippet = "";
16215
- this.finishRetryCount = 0;
16216
- this.currentTurnScope = null;
16217
- this.activeModal = null;
16218
- this.setStatus("idle", "parsed_idle_replay_commit");
16219
- this.onStatusChange?.();
16220
- }
16221
- }
16222
- const shouldPreferCommittedHistoryReplay = !this.currentTurnScope && !this.activeModal && this.committedMessages.length > parsedHydratedMessages.length;
16223
- const shouldPreferCommittedIdleReplay = shouldPreferCommittedMessages && !shouldAdoptParsedIdleReplay;
16224
- const hydratedMessages = shouldPreferCommittedIdleReplay || shouldPreferCommittedHistoryReplay ? this.buildCommittedChatMessages() : parsedHydratedMessages;
16225
- result = {
16226
- id: parsed.id || "cli_session",
16227
- status: parsed.status || this.currentStatus,
16228
- title: parsed.title || this.cliName,
16229
- messages: hydratedMessages,
16230
- activeModal: parsed.activeModal ?? this.activeModal,
16231
- providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
16232
- ...this.getBufferState() ? { bufferState: this.getBufferState() } : {},
16233
- ...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
16234
- };
16235
- } else {
16236
- const messages = [...this.committedMessages];
16237
- const bufferState = this.getBufferState();
16238
- result = {
16239
- id: "cli_session",
16240
- status: this.currentStatus,
16241
- title: this.cliName,
16242
- messages: messages.map((message, index) => buildChatMessage({
16243
- ...message,
16244
- id: message.id || `msg_${index}`,
16245
- index: typeof message.index === "number" ? message.index : index,
16246
- receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
16247
- })),
16248
- activeModal: this.activeModal,
16249
- ...bufferState ? { bufferState } : {}
16250
- };
16251
- }
16252
- const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
16253
- const shouldClampStaleGeneratingToIdle = result?.status === "generating" && this.currentStatus === "idle" && !this.currentTurnScope && !result?.activeModal && hasVisibleAssistantMessage && !hasVisibleInterruptPrompt(screenText);
16254
- if (shouldClampStaleGeneratingToIdle) {
16255
- result = {
16256
- ...result,
16257
- status: "idle",
16258
- messages: Array.isArray(result.messages) ? result.messages.map((message) => {
16259
- if (message?.role !== "assistant" || !message?.meta?.streaming) return message;
16260
- const nextMeta = { ...message.meta || {} };
16261
- delete nextMeta.streaming;
16262
- return {
16263
- ...message,
16264
- ...Object.keys(nextMeta).length > 0 ? { meta: nextMeta } : { meta: void 0 }
16265
- };
16266
- }) : result.messages
16267
- };
16268
- }
15358
+ }),
15359
+ activeModal,
15360
+ providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
15361
+ ...bufferState ? { bufferState } : {},
15362
+ ...parsed.transcriptAuthority === "provider" || parsed.transcriptAuthority === "daemon" ? { transcriptAuthority: parsed.transcriptAuthority } : this.providerOwnsTranscript() ? { transcriptAuthority: "provider" } : {},
15363
+ ...parsed.coverage === "full" || parsed.coverage === "tail" || parsed.coverage === "current-turn" ? { coverage: parsed.coverage } : this.providerOwnsTranscript() ? { coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
15364
+ };
16269
15365
  this.parsedStatusCache = {
16270
- committedMessagesRef: this.committedMessages,
16271
15366
  responseBuffer: this.responseBuffer,
16272
15367
  currentTurnScope: this.currentTurnScope,
16273
15368
  recentOutputBuffer: this.recentOutputBuffer,
@@ -16290,7 +15385,7 @@ var init_provider_cli_adapter = __esm({
16290
15385
  accumulatedRawBuffer: this.accumulatedRawBuffer,
16291
15386
  recentOutputBuffer: this.recentOutputBuffer,
16292
15387
  terminalScreenText: this.terminalScreen.getText(),
16293
- baseMessages: this.committedMessages,
15388
+ baseMessages: [],
16294
15389
  partialResponse: this.responseBuffer,
16295
15390
  isWaitingForResponse: this.isWaitingForResponse,
16296
15391
  scope: this.currentTurnScope,
@@ -16301,46 +15396,8 @@ var init_provider_cli_adapter = __esm({
16301
15396
  args: args && typeof args === "object" ? { ...args } : {}
16302
15397
  }));
16303
15398
  }
16304
- parseCurrentTranscript(baseMessages, partialResponse, scope, screenTextOverride) {
16305
- if (!this.cliScripts?.parseOutput) {
16306
- this.parseErrorMessage = null;
16307
- return null;
16308
- }
16309
- try {
16310
- const screenText = typeof screenTextOverride === "string" ? screenTextOverride : this.terminalScreen.getText();
16311
- const parseBaseMessages = this.selectParseBaseMessages(baseMessages);
16312
- const input = buildCliParseInput({
16313
- accumulatedBuffer: this.accumulatedBuffer,
16314
- accumulatedRawBuffer: this.accumulatedRawBuffer,
16315
- recentOutputBuffer: this.recentOutputBuffer,
16316
- terminalScreenText: screenText,
16317
- baseMessages: parseBaseMessages,
16318
- partialResponse,
16319
- isWaitingForResponse: this.isWaitingForResponse,
16320
- scope,
16321
- runtimeSettings: this.runtimeSettings
16322
- });
16323
- const parsed = this.cliScripts.parseOutput(input);
16324
- if (parsed && typeof parsed === "object") {
16325
- Object.assign(parsed, validateReadChatResultPayload(parsed, `${this.cliType} parseOutput`));
16326
- }
16327
- const normalizedParsed = this.suppressStaleParsedApproval(parsed, input.recentBuffer, input.screenText);
16328
- if (normalizedParsed && Array.isArray(normalizedParsed.messages)) {
16329
- normalizedParsed.messages = this.stitchParsedMessagesWithCommittedBase(
16330
- normalizedParsed.messages,
16331
- baseMessages,
16332
- parseBaseMessages
16333
- );
16334
- this.trimLastAssistantEcho(normalizedParsed.messages, scope?.prompt || getLastUserPromptText(baseMessages));
16335
- }
16336
- this.parseErrorMessage = null;
16337
- return normalizedParsed;
16338
- } catch (e) {
16339
- const message = e?.message || String(e);
16340
- this.parseErrorMessage = message;
16341
- LOG.warn("CLI", `[${this.cliType}] parseOutput error: ${message}`);
16342
- throw e;
16343
- }
15399
+ parseCurrentTranscript(_baseMessages, _partialResponse, _scope, _screenTextOverride) {
15400
+ return this.runParseSession();
16344
15401
  }
16345
15402
  /** Whether this adapter has CLI scripts loaded */
16346
15403
  hasCliScripts() {
@@ -16402,8 +15459,6 @@ var init_provider_cli_adapter = __esm({
16402
15459
  commitSendUserTurn(state) {
16403
15460
  if (state.didCommitUserTurn) return;
16404
15461
  state.didCommitUserTurn = true;
16405
- this.committedMessages.push({ role: "user", content: state.text, timestamp: Date.now() });
16406
- this.syncMessageViews();
16407
15462
  }
16408
15463
  armResponseTimeout() {
16409
15464
  if (this.responseTimeout) clearTimeout(this.responseTimeout);
@@ -16595,11 +15650,6 @@ var init_provider_cli_adapter = __esm({
16595
15650
  }
16596
15651
  })() : null;
16597
15652
  const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
16598
- const parsedMessagesBeforeSend = Array.isArray(parsedStatusBeforeSend?.messages) ? parsedStatusBeforeSend.messages.filter((message) => message && (message.role === "user" || message.role === "assistant")) : [];
16599
- const shouldCommitParsedIdleBeforeSend = !allowInputDuringGeneration && parsedSessionStatus === "idle" && parsedMessagesBeforeSend.length > this.committedMessages.length && parsedMessagesBeforeSend.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
16600
- if (shouldCommitParsedIdleBeforeSend) {
16601
- this.commitCurrentTranscript();
16602
- }
16603
15653
  if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
16604
15654
  throw new Error(`${this.cliName} is still processing the previous prompt`);
16605
15655
  }
@@ -16705,9 +15755,6 @@ var init_provider_cli_adapter = __esm({
16705
15755
  activeModal: this.activeModal,
16706
15756
  parseErrorMessage: this.parseErrorMessage,
16707
15757
  messageCounts: {
16708
- committed: this.committedMessages.length,
16709
- structured: this.structuredMessages.length,
16710
- visible: this.messages.length,
16711
15758
  parsedCache: Array.isArray(parsedResult?.messages) ? parsedResult.messages.length : void 0
16712
15759
  },
16713
15760
  buffers: {
@@ -16758,8 +15805,7 @@ var init_provider_cli_adapter = __esm({
16758
15805
  responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
16759
15806
  responseEpoch: this.responseEpoch,
16760
15807
  resizeSuppressUntil: this.resizeSuppressUntil,
16761
- lastApprovalResolvedAt: this.lastApprovalResolvedAt,
16762
- committedMessagesChangedAt: this.committedMessagesChangedAt
15808
+ lastApprovalResolvedAt: this.lastApprovalResolvedAt
16763
15809
  },
16764
15810
  finish: {
16765
15811
  idleFinishCandidate: this.idleFinishCandidate,
@@ -16884,8 +15930,6 @@ var init_provider_cli_adapter = __esm({
16884
15930
  }
16885
15931
  clearHistory() {
16886
15932
  this.clearIdleFinishCandidate("clear_history");
16887
- this.committedMessages = [];
16888
- this.syncMessageViews();
16889
15933
  this.accumulatedBuffer = "";
16890
15934
  this.accumulatedRawBuffer = "";
16891
15935
  this.currentTurnScope = null;
@@ -16926,7 +15970,7 @@ var init_provider_cli_adapter = __esm({
16926
15970
  }
16927
15971
  resolveModal(buttonIndex) {
16928
15972
  let modal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
16929
- if (!modal && typeof this.cliScripts?.parseOutput === "function") {
15973
+ if (!modal && typeof this.cliScripts?.parseSession === "function") {
16930
15974
  try {
16931
15975
  const parsed = this.getScriptParsedStatus();
16932
15976
  const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
@@ -16993,10 +16037,8 @@ var init_provider_cli_adapter = __esm({
16993
16037
  startupParseGate: this.startupParseGate,
16994
16038
  spawnAt: this.spawnAt,
16995
16039
  workingDir: this.workingDir,
16996
- messages: this.messages,
16997
- committedMessages: this.committedMessages,
16998
- structuredMessages: this.structuredMessages,
16999
- messageCount: this.committedMessages.length,
16040
+ messages: [],
16041
+ messageCount: 0,
17000
16042
  screenText: screenText.slice(-4e3),
17001
16043
  currentTurnScope: this.currentTurnScope,
17002
16044
  startupBuffer: this.startupBuffer.slice(-4e3),
@@ -17048,7 +16090,7 @@ var init_provider_cli_adapter = __esm({
17048
16090
  lifecycleStatus: this.isWaitingForResponse ? "awaiting_response" : "idle",
17049
16091
  activeModal: this.activeModal,
17050
16092
  currentTurnScope: this.currentTurnScope,
17051
- messages: summarizeCliTraceMessages(this.committedMessages, 5)
16093
+ messages: []
17052
16094
  };
17053
16095
  }
17054
16096
  getProviderResolutionMeta() {
@@ -17341,17 +16383,11 @@ var init_cli_provider_instance = __esm({
17341
16383
  }
17342
16384
  const runtime = this.adapter.getRuntimeMetadata();
17343
16385
  this.maybeAppendRuntimeRecoveryMessage(runtime);
17344
- let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : parseErrorMessage ? normalizeChatMessages(Array.isArray(adapterStatus.messages) ? adapterStatus.messages : []) : [];
16386
+ let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
17345
16387
  const historyMessageCount = Number.isFinite(parsedStatus?.historyMessageCount) ? Math.max(0, Number(parsedStatus.historyMessageCount)) : null;
17346
16388
  if (historyMessageCount !== null) {
17347
16389
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
17348
16390
  }
17349
- const committedMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
17350
- const isActiveNonIdle = adapterStatus.status !== "idle";
17351
- const shouldApplyCommittedFloor = parsedMessages.length < committedMessages.length && (adapterStatus.status === "waiting_approval" || isActiveNonIdle && historyMessageCount === null);
17352
- if (shouldApplyCommittedFloor) {
17353
- parsedMessages = normalizeChatMessages(committedMessages);
17354
- }
17355
16391
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
17356
16392
  const canonicalBackedHistory = this.syncCanonicalSavedHistoryIfNeeded();
17357
16393
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
@@ -17444,11 +16480,9 @@ var init_cli_provider_instance = __esm({
17444
16480
  const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
17445
16481
  const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
17446
16482
  const runtime = this.adapter.getRuntimeMetadata();
17447
- const lastCommittedMessageActivityAt = typeof this.adapter.getLastCommittedMessageActivityAt === "function" ? this.adapter.getLastCommittedMessageActivityAt() : 0;
17448
16483
  return {
17449
16484
  id: this.instanceId,
17450
16485
  status: visibleStatus,
17451
- lastMessageAt: lastCommittedMessageActivityAt || void 0,
17452
16486
  runtimeLifecycle: runtime?.lifecycle ?? null,
17453
16487
  runtimeSurfaceKind: runtime?.surfaceKind,
17454
16488
  runtimeRestoredFromStorage: runtime?.restoredFromStorage === true,
@@ -17554,7 +16588,7 @@ var init_cli_provider_instance = __esm({
17554
16588
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
17555
16589
  const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
17556
16590
  const partial2 = this.adapter.getPartialResponse();
17557
- const progressFingerprint = newStatus === "generating" ? `${partial2 || ""}::${adapterStatus.messages.at(-1)?.content || ""}`.slice(-2e3) : void 0;
16591
+ const progressFingerprint = newStatus === "generating" ? `${partial2 || ""}`.slice(-2e3) : void 0;
17558
16592
  const previousStatus = this.lastStatus;
17559
16593
  if (newStatus !== this.lastStatus) {
17560
16594
  LOG.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
@@ -18000,18 +17034,6 @@ ${effect.notification.body || ""}`.trim();
18000
17034
  receivedAt: message.receivedAt
18001
17035
  }));
18002
17036
  this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
18003
- if (restoredHistory.messages.length > 0) {
18004
- this.adapter.seedCommittedMessages(
18005
- restoredHistory.messages.map((message) => ({
18006
- role: message.role,
18007
- content: message.content,
18008
- timestamp: message.receivedAt,
18009
- receivedAt: message.receivedAt,
18010
- kind: message.kind,
18011
- senderName: message.senderName
18012
- }))
18013
- );
18014
- }
18015
17037
  }
18016
17038
  getProbeDirectories() {
18017
17039
  const dirs = /* @__PURE__ */ new Set();
@@ -40239,13 +39261,24 @@ async function launchWithCdp(options = {}) {
40239
39261
  break;
40240
39262
  }
40241
39263
  }
39264
+ if (!cdpReady) {
39265
+ return {
39266
+ success: false,
39267
+ ideId: targetIde.id,
39268
+ ideName: targetIde.displayName,
39269
+ port,
39270
+ action: "failed",
39271
+ message: "",
39272
+ error: `${targetIde.displayName} launched but CDP did not become available on port ${port}`
39273
+ };
39274
+ }
40242
39275
  return {
40243
39276
  success: true,
40244
39277
  ideId: targetIde.id,
40245
39278
  ideName: targetIde.displayName,
40246
39279
  port,
40247
39280
  action: alreadyRunning ? "restarted" : "started",
40248
- message: cdpReady ? `${targetIde.displayName} launched with CDP on port ${port}` : `${targetIde.displayName} launched (CDP may take a moment to initialize)`
39281
+ message: `${targetIde.displayName} launched with CDP on port ${port}`
40249
39282
  };
40250
39283
  } catch (e) {
40251
39284
  return {
@@ -42242,9 +41275,6 @@ var init_ipc_protocol = __esm({
42242
41275
  });
42243
41276
 
42244
41277
  // ../../oss/packages/daemon-core/src/chat/subscription-updates.ts
42245
- function normalizeSyncMode(syncMode) {
42246
- return syncMode === "append" || syncMode === "replace_tail" || syncMode === "noop" || syncMode === "full" ? syncMode : "full";
42247
- }
42248
41278
  function normalizeModalButtons(value) {
42249
41279
  return Array.isArray(value) ? value.filter((button) => typeof button === "string") : [];
42250
41280
  }
@@ -42271,55 +41301,39 @@ function normalizeSessionModalFields(activeModal) {
42271
41301
  modalButtons: normalizeModalButtons(activeModal.buttons)
42272
41302
  };
42273
41303
  }
42274
- function buildNextChatCursor(cursor, result) {
42275
- return {
42276
- knownMessageCount: Math.max(0, Number(result.totalMessages || cursor.knownMessageCount)),
42277
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : cursor.lastMessageSignature,
42278
- tailLimit: cursor.tailLimit
42279
- };
42280
- }
42281
41304
  function prepareSessionChatTailUpdate(input) {
42282
41305
  const result = input.result;
42283
- if (!result?.success || result.syncMode === "noop") {
41306
+ if (!result?.success) {
42284
41307
  return {
42285
- cursor: result?.success ? buildNextChatCursor(input.cursor, result) : input.cursor,
41308
+ cursor: input.cursor,
42286
41309
  seq: input.seq,
42287
41310
  lastDeliveredSignature: input.lastDeliveredSignature,
42288
41311
  update: null
42289
41312
  };
42290
41313
  }
42291
- const syncMode = normalizeSyncMode(result.syncMode);
42292
- const cursor = {
42293
- knownMessageCount: Math.max(0, Number(result.totalMessages || 0)),
42294
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : "",
42295
- tailLimit: input.cursor.tailLimit
42296
- };
41314
+ const messages = Array.isArray(result.messages) ? result.messages : [];
42297
41315
  const title = typeof result.title === "string" ? result.title : void 0;
42298
41316
  const activeModal = normalizeChatTailActiveModal(result.activeModal);
42299
41317
  const status = typeof result.status === "string" ? result.status : "idle";
42300
41318
  const deliverySignature = buildChatTailDeliverySignature({
42301
41319
  sessionId: input.sessionId,
42302
41320
  ...input.historySessionId ? { historySessionId: input.historySessionId } : {},
42303
- messages: Array.isArray(result.messages) ? result.messages : [],
41321
+ messages,
42304
41322
  status,
42305
41323
  ...title ? { title } : {},
42306
- ...activeModal ? { activeModal } : {},
42307
- syncMode,
42308
- replaceFrom: Number(result.replaceFrom || 0),
42309
- totalMessages: Number(result.totalMessages || 0),
42310
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
41324
+ ...activeModal ? { activeModal } : {}
42311
41325
  });
42312
41326
  const seq = input.seq + 1;
42313
41327
  if (deliverySignature === input.lastDeliveredSignature) {
42314
41328
  return {
42315
- cursor,
41329
+ cursor: input.cursor,
42316
41330
  seq,
42317
41331
  lastDeliveredSignature: input.lastDeliveredSignature,
42318
41332
  update: null
42319
41333
  };
42320
41334
  }
42321
41335
  return {
42322
- cursor,
41336
+ cursor: input.cursor,
42323
41337
  seq,
42324
41338
  lastDeliveredSignature: deliverySignature,
42325
41339
  update: {
@@ -42330,14 +41344,10 @@ function prepareSessionChatTailUpdate(input) {
42330
41344
  ...input.interactionId ? { interactionId: input.interactionId } : {},
42331
41345
  seq,
42332
41346
  timestamp: input.timestamp,
42333
- messages: Array.isArray(result.messages) ? result.messages : [],
41347
+ messages,
42334
41348
  status,
42335
41349
  ...title ? { title } : {},
42336
- ...activeModal ? { activeModal } : {},
42337
- syncMode,
42338
- replaceFrom: Number(result.replaceFrom || 0),
42339
- totalMessages: Number(result.totalMessages || 0),
42340
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
41350
+ ...activeModal ? { activeModal } : {}
42341
41351
  }
42342
41352
  };
42343
41353
  }
@@ -47075,7 +46085,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
47075
46085
  lines.push("Provider category: `cli`");
47076
46086
  lines.push("");
47077
46087
  const funcToFile = {
47078
- parseOutput: "parse_output.js",
46088
+ parseSession: "parse_session.js",
47079
46089
  detectStatus: "detect_status.js",
47080
46090
  parseApproval: "parse_approval.js"
47081
46091
  };
@@ -47164,7 +46174,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
47164
46174
  lines.push("");
47165
46175
  lines.push("| Function | Input | Return |");
47166
46176
  lines.push("|---|---|---|");
47167
- lines.push("| `parseOutput` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |");
46177
+ lines.push("| `parseSession` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |");
47168
46178
  lines.push("| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |");
47169
46179
  lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
47170
46180
  lines.push("");
@@ -47384,7 +46394,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
47384
46394
  lines.push("");
47385
46395
  lines.push("## Required Validation");
47386
46396
  lines.push("1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.");
47387
- lines.push("2. Confirm `parseOutput` produces a stable transcript without duplicating past turns when the PTY redraws.");
46397
+ lines.push("2. Confirm `parseSession` produces a stable transcript without duplicating past turns when the PTY redraws.");
47388
46398
  lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
47389
46399
  lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
47390
46400
  lines.push("5. Confirm the Python file was actually created and executed, not just described in chat text.");
@@ -48683,7 +47693,7 @@ var init_dev_server = __esm({
48683
47693
  lines.push("Provider category: `cli`");
48684
47694
  lines.push("");
48685
47695
  const funcToFile = {
48686
- parseOutput: "parse_output.js",
47696
+ parseSession: "parse_session.js",
48687
47697
  detectStatus: "detect_status.js",
48688
47698
  parseApproval: "parse_approval.js"
48689
47699
  };
@@ -48772,7 +47782,7 @@ var init_dev_server = __esm({
48772
47782
  lines.push("");
48773
47783
  lines.push("| Function | Input | Return |");
48774
47784
  lines.push("|---|---|---|");
48775
- lines.push("| `parseOutput` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |");
47785
+ lines.push("| `parseSession` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |");
48776
47786
  lines.push("| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |");
48777
47787
  lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
48778
47788
  lines.push("");
@@ -48867,7 +47877,7 @@ var init_dev_server = __esm({
48867
47877
  lines.push("");
48868
47878
  lines.push("## Required Validation");
48869
47879
  lines.push("1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.");
48870
- lines.push("2. Confirm `parseOutput` produces a stable transcript without duplicating past turns when the PTY redraws.");
47880
+ lines.push("2. Confirm `parseSession` produces a stable transcript without duplicating past turns when the PTY redraws.");
48871
47881
  lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
48872
47882
  lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
48873
47883
  lines.push("5. Confirm the Python file was actually created and executed, not just described in chat text.");
@@ -81659,8 +80669,6 @@ function handleSubscribe(peerId, msg, peers, handlers) {
81659
80669
  params,
81660
80670
  seq: 0,
81661
80671
  cursor: {
81662
- knownMessageCount: Math.max(0, Number(params.knownMessageCount || 0)),
81663
- lastMessageSignature: typeof params.lastMessageSignature === "string" ? params.lastMessageSignature : "",
81664
80672
  tailLimit: Math.max(0, Number(params.tailLimit || 0))
81665
80673
  },
81666
80674
  lastDeliveredSignature: ""
@@ -82700,12 +81708,8 @@ ${e?.stack || ""}`);
82700
81708
  sessionId: subscription.params.targetSessionId,
82701
81709
  seq: subscription.seq,
82702
81710
  timestamp: Date.now(),
82703
- syncMode: "noop",
82704
81711
  messages: [],
82705
81712
  status: "",
82706
- replaceFrom: 0,
82707
- totalMessages: 0,
82708
- lastMessageSignature: "",
82709
81713
  error: error48?.message || "chat_tail build failed"
82710
81714
  };
82711
81715
  this.screenshotSender.sendTopicUpdateToPeer(peer, errorUpdate);
@@ -90388,7 +89392,7 @@ var init_adhdev_daemon = __esm({
90388
89392
  init_version();
90389
89393
  init_src();
90390
89394
  init_runtime_defaults();
90391
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.63" });
89395
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.65" });
90392
89396
  AdhdevDaemon = class _AdhdevDaemon {
90393
89397
  localHttpServer = null;
90394
89398
  localWss = null;
@@ -90548,8 +89552,6 @@ var init_adhdev_daemon = __esm({
90548
89552
  const result = await this.components.router.execute("read_chat", {
90549
89553
  targetSessionId: subscription.params.targetSessionId,
90550
89554
  ...subscription.params.historySessionId ? { historySessionId: subscription.params.historySessionId } : {},
90551
- knownMessageCount: subscription.cursor.knownMessageCount,
90552
- lastMessageSignature: subscription.cursor.lastMessageSignature,
90553
89555
  ...subscription.cursor.tailLimit > 0 ? { tailLimit: subscription.cursor.tailLimit } : {}
90554
89556
  }, "p2p");
90555
89557
  const interactionId = this.getSessionInteractionId(subscription.params.targetSessionId);
@@ -90577,9 +89579,7 @@ var init_adhdev_daemon = __esm({
90577
89579
  level: "info",
90578
89580
  sessionId: subscription.params.targetSessionId,
90579
89581
  payload: {
90580
- syncMode: prepared.update.syncMode,
90581
- totalMessages: prepared.update.totalMessages,
90582
- replaceFrom: prepared.update.replaceFrom,
89582
+ returnedMessages: prepared.update.messages.length,
90583
89583
  hasModal: !!prepared.update.activeModal,
90584
89584
  hasTitle: typeof prepared.update.title === "string"
90585
89585
  }