adhdev 0.9.64 → 0.9.66

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,127 +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 isReadChatConversationAnchorMessage(message) {
9413
- if (!message) return false;
9414
- const role = String(message.role || "").trim().toLowerCase();
9415
- if (role !== "user" && role !== "assistant") return false;
9416
- const kind = String(message.kind || "standard").trim().toLowerCase();
9417
- return !kind || kind === "standard";
9418
- }
9419
- function buildVisibleReadChatTailMessages(messages, tailLimit) {
9420
- const totalMessages = messages.length;
9421
- if (tailLimit <= 0 || totalMessages <= tailLimit) return messages;
9422
- const tailMessages = messages.slice(-tailLimit);
9423
- if (tailMessages.some(isReadChatConversationAnchorMessage)) return tailMessages;
9424
- const hiddenMessages = messages.slice(0, totalMessages - tailLimit);
9425
- const anchors = [];
9426
- const seenRoles = /* @__PURE__ */ new Set();
9427
- for (let index = hiddenMessages.length - 1; index >= 0 && anchors.length < 2; index -= 1) {
9428
- const message = hiddenMessages[index];
9429
- if (!isReadChatConversationAnchorMessage(message)) continue;
9430
- const role = String(message.role || "").trim().toLowerCase();
9431
- if (seenRoles.has(role)) continue;
9432
- seenRoles.add(role);
9433
- anchors.unshift(message);
9434
- }
9435
- return anchors.length > 0 ? [...anchors, ...tailMessages] : tailMessages;
9436
- }
9437
- function buildBoundedTailSync(messages, cursor) {
9313
+ function buildFullTail(messages, tailLimit) {
9438
9314
  const totalMessages = messages.length;
9439
- const tailMessages = buildVisibleReadChatTailMessages(messages, cursor.tailLimit);
9315
+ const tailMessages = tailLimit > 0 ? messages.slice(-tailLimit) : messages;
9440
9316
  return {
9441
- syncMode: "full",
9442
- replaceFrom: 0,
9443
9317
  messages: tailMessages,
9444
- totalMessages,
9445
- lastMessageSignature: getChatMessageSignature(messages[totalMessages - 1])
9446
- };
9447
- }
9448
- function computeReadChatSync(messages, cursor) {
9449
- const totalMessages = messages.length;
9450
- const lastMessageSignature = getChatMessageSignature(messages[totalMessages - 1]);
9451
- const { knownMessageCount, lastMessageSignature: knownSignature } = cursor;
9452
- if (!knownMessageCount || !knownSignature) {
9453
- return {
9454
- syncMode: "full",
9455
- replaceFrom: 0,
9456
- messages,
9457
- totalMessages,
9458
- lastMessageSignature
9459
- };
9460
- }
9461
- if (knownMessageCount > totalMessages) {
9462
- return {
9463
- syncMode: "full",
9464
- replaceFrom: 0,
9465
- messages,
9466
- totalMessages,
9467
- lastMessageSignature
9468
- };
9469
- }
9470
- if (knownMessageCount === totalMessages && knownSignature === lastMessageSignature) {
9471
- return {
9472
- syncMode: "noop",
9473
- replaceFrom: totalMessages,
9474
- messages: [],
9475
- totalMessages,
9476
- lastMessageSignature
9477
- };
9478
- }
9479
- if (cursor.tailLimit > 0 && knownSignature === lastMessageSignature) {
9480
- const requestedTailCount = Math.min(totalMessages, cursor.tailLimit);
9481
- if (knownMessageCount >= requestedTailCount) {
9482
- return {
9483
- syncMode: "noop",
9484
- replaceFrom: totalMessages,
9485
- messages: [],
9486
- totalMessages,
9487
- lastMessageSignature
9488
- };
9489
- }
9490
- return buildBoundedTailSync(messages, cursor);
9491
- }
9492
- if (knownMessageCount < totalMessages) {
9493
- const anchorSignature = getChatMessageSignature(messages[knownMessageCount - 1]);
9494
- if (anchorSignature === knownSignature) {
9495
- return {
9496
- syncMode: "append",
9497
- replaceFrom: knownMessageCount,
9498
- messages: messages.slice(knownMessageCount),
9499
- totalMessages,
9500
- lastMessageSignature
9501
- };
9502
- }
9503
- if (cursor.tailLimit > 0) {
9504
- const signatureIndex = findLastMessageIndexBySignature(messages, knownSignature);
9505
- if (signatureIndex >= 0) {
9506
- return {
9507
- syncMode: "append",
9508
- replaceFrom: knownMessageCount,
9509
- messages: messages.slice(signatureIndex + 1),
9510
- totalMessages,
9511
- lastMessageSignature
9512
- };
9513
- }
9514
- return buildBoundedTailSync(messages, cursor);
9515
- }
9516
- }
9517
- const replaceFrom = Math.max(0, Math.min(knownMessageCount - 1, totalMessages));
9518
- return {
9519
- syncMode: replaceFrom === 0 ? "full" : "replace_tail",
9520
- replaceFrom,
9521
- messages: replaceFrom === 0 ? messages : messages.slice(replaceFrom),
9522
- totalMessages,
9523
- lastMessageSignature
9318
+ totalMessages
9524
9319
  };
9525
9320
  }
9526
9321
  function hasNonEmptyModalButtons(activeModal) {
@@ -9555,31 +9350,13 @@ function buildReadChatCommandResult(payload, args) {
9555
9350
  } catch (error48) {
9556
9351
  return { success: false, error: error48?.message || String(error48) };
9557
9352
  }
9558
- const messages = collapseReplayDuplicatesFromReadChat(normalizeReadChatMessages(validatedPayload));
9559
- const cursor = normalizeReadChatCursor(args);
9560
- if (!cursor.knownMessageCount && !cursor.lastMessageSignature && cursor.tailLimit > 0 && messages.length > cursor.tailLimit) {
9561
- const tailMessages = buildVisibleReadChatTailMessages(messages, cursor.tailLimit);
9562
- const lastMessageSignature = getChatMessageSignature(messages[messages.length - 1]);
9563
- return {
9564
- success: true,
9565
- ...validatedPayload,
9566
- messages: tailMessages,
9567
- syncMode: "full",
9568
- replaceFrom: 0,
9569
- totalMessages: messages.length,
9570
- lastMessageSignature,
9571
- ...debugReadChat ? { debugReadChat } : {}
9572
- };
9573
- }
9574
- const sync = computeReadChatSync(messages, cursor);
9353
+ const messages = normalizeReadChatMessages(validatedPayload);
9354
+ const sync = buildFullTail(messages, normalizeReadChatTailLimit(args));
9575
9355
  return {
9576
9356
  success: true,
9577
9357
  ...validatedPayload,
9578
9358
  messages: sync.messages,
9579
- syncMode: sync.syncMode,
9580
- replaceFrom: sync.replaceFrom,
9581
9359
  totalMessages: sync.totalMessages,
9582
- lastMessageSignature: sync.lastMessageSignature,
9583
9360
  ...debugReadChat ? { debugReadChat } : {}
9584
9361
  };
9585
9362
  }
@@ -9797,10 +9574,6 @@ async function handleGetChatDebugBundle(h, args) {
9797
9574
  status: readResult.status,
9798
9575
  title: readResult.title,
9799
9576
  totalMessages: readResult.totalMessages,
9800
- returnedMessages: Array.isArray(readResult.messages) ? readResult.messages.length : void 0,
9801
- syncMode: readResult.syncMode,
9802
- replaceFrom: readResult.replaceFrom,
9803
- lastMessageSignature: readResult.lastMessageSignature,
9804
9577
  providerSessionId: readResult.providerSessionId,
9805
9578
  transcriptAuthority: readResult.transcriptAuthority,
9806
9579
  coverage: readResult.coverage,
@@ -9910,22 +9683,13 @@ function toNonNegativeNumber(value) {
9910
9683
  return Number.isFinite(numeric) ? Math.max(0, numeric) : 0;
9911
9684
  }
9912
9685
  function getCliVisibleTranscriptCount(adapter) {
9913
- const adapterStatus = adapter?.getStatus?.() || {};
9914
- const adapterMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
9915
- let parsedRecord = null;
9916
- if (typeof adapter?.getScriptParsedStatus === "function") {
9917
- try {
9918
- const parsed = parseMaybeJson(adapter.getScriptParsedStatus());
9919
- parsedRecord = parsed && typeof parsed === "object" ? parsed : null;
9920
- } catch {
9921
- parsedRecord = null;
9922
- }
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;
9923
9692
  }
9924
- const parsedMessages = Array.isArray(parsedRecord?.messages) ? parsedRecord.messages : [];
9925
- if (!parsedRecord) return adapterMessages.length;
9926
- const parsedIsProviderAuthoritative = parsedRecord.transcriptAuthority === "provider" || parsedRecord.coverage === "full";
9927
- const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && adapterMessages.length > 0 && adapterMessages.length > parsedMessages.length;
9928
- return shouldPreferAdapterMessages ? adapterMessages.length : parsedMessages.length;
9929
9693
  }
9930
9694
  async function getStableExtensionBaseline(h) {
9931
9695
  const first = await readExtensionChatState(h);
@@ -9987,52 +9751,46 @@ async function handleReadChat(h, args) {
9987
9751
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
9988
9752
  if (adapter) {
9989
9753
  _log(`${transport} adapter: ${adapter.cliType}`);
9754
+ if (typeof adapter.getScriptParsedStatus !== "function") {
9755
+ return { success: false, error: `${transport} adapter parseSession unavailable` };
9756
+ }
9990
9757
  let parsedStatus = null;
9991
- if (typeof adapter.getScriptParsedStatus === "function") {
9992
- try {
9993
- parsedStatus = parseMaybeJson(adapter.getScriptParsedStatus());
9994
- } catch (error48) {
9995
- return { success: false, error: error48?.message || String(error48) };
9996
- }
9758
+ try {
9759
+ parsedStatus = parseMaybeJson(adapter.getScriptParsedStatus());
9760
+ } catch (error48) {
9761
+ return { success: false, error: error48?.message || String(error48) };
9997
9762
  }
9998
9763
  const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
9999
- const adapterStatus = adapter.getStatus();
10000
- const parsedIsProviderAuthoritative = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.coverage === "full";
10001
- const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
10002
- const parsedShowsApproval = hasNonEmptyModalButtons(parsedRecord?.activeModal) && parsedRecord?.status === "waiting_approval";
10003
- const status = parsedRecord ? {
10004
- ...parsedRecord,
10005
- messages: shouldPreferAdapterMessages ? adapterStatus.messages : parsedRecord.messages,
10006
- status: parsedShowsApproval ? parsedRecord.status : adapterStatus.status !== "idle" ? adapterStatus.status : parsedRecord.status || adapterStatus.status,
10007
- activeModal: parsedRecord.activeModal || adapterStatus.activeModal
10008
- } : adapterStatus;
10009
- const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
10010
- const providerSessionId = typeof parsedRecord?.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
10011
- const transcriptAuthority = parsedRecord?.transcriptAuthority === "provider" || parsedRecord?.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
10012
- const coverage = parsedRecord?.coverage === "full" || parsedRecord?.coverage === "tail" || parsedRecord?.coverage === "current-turn" ? parsedRecord.coverage : void 0;
10013
- if (status) {
10014
- 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}`);
10015
- return buildReadChatCommandResult({
10016
- messages: status.messages || [],
10017
- status: status.status,
10018
- activeModal: status.activeModal,
10019
- debugReadChat: {
10020
- provider: adapter.cliType,
10021
- targetSessionId: String(args?.targetSessionId || ""),
10022
- adapterStatus: String(adapterStatus.status || ""),
10023
- parsedStatus: String(parsedRecord?.status || ""),
10024
- returnedStatus: String(status.status || ""),
10025
- shouldPreferAdapterMessages,
10026
- adapterMsgCount: Array.isArray(adapterStatus.messages) ? adapterStatus.messages.length : 0,
10027
- parsedMsgCount: Array.isArray(parsedRecord?.messages) ? parsedRecord.messages.length : 0,
10028
- returnedMsgCount: Array.isArray(status.messages) ? status.messages.length : 0
10029
- },
10030
- ...title ? { title } : {},
10031
- ...providerSessionId ? { providerSessionId } : {},
10032
- ...transcriptAuthority ? { transcriptAuthority } : {},
10033
- ...coverage ? { coverage } : {}
10034
- }, args);
10035
- }
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);
10036
9794
  }
10037
9795
  return { success: false, error: `${transport} adapter not found` };
10038
9796
  }
@@ -10886,7 +10644,6 @@ var init_chat_commands = __esm({
10886
10644
  init_logger();
10887
10645
  init_debug_trace();
10888
10646
  init_chat_signatures();
10889
- init_chat_message_normalization();
10890
10647
  RECENT_SEND_WINDOW_MS = 1200;
10891
10648
  READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25e3;
10892
10649
  recentSendByTarget = /* @__PURE__ */ new Map();
@@ -14063,67 +13820,6 @@ function promptLikelyVisible(screenText, promptSnippet) {
14063
13820
  function normalizeScreenSnapshot(text) {
14064
13821
  return sanitizeTerminalText(String(text || "")).replace(/\s+/g, " ").trim();
14065
13822
  }
14066
- function shouldReflowComparableMessageLines(lines) {
14067
- 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));
14068
- }
14069
- function joinComparableMessageLines(lines) {
14070
- return lines.reduce((acc, line) => {
14071
- const next = String(line || "").trim();
14072
- if (!next) return acc;
14073
- if (!acc) return next;
14074
- if (/[,\d]$/.test(acc) && /^\d/.test(next)) {
14075
- return `${acc}${next}`;
14076
- }
14077
- if (/[A-Za-z]$/.test(acc) && /^\d/.test(next)) {
14078
- return `${acc}${next}`;
14079
- }
14080
- const fragmentMatch = acc.match(/([A-Za-z]{1,4})$/);
14081
- const fragment = fragmentMatch ? fragmentMatch[1].toLowerCase() : "";
14082
- if (/^[a-z]/.test(next) && fragment && !COMMON_COMPARABLE_WRAP_WORDS.has(fragment)) {
14083
- return `${acc}${next}`;
14084
- }
14085
- return `${acc} ${next}`;
14086
- }, "").replace(/\s+([,.;:!?])/g, "$1").replace(/(\d)\s+,/g, "$1,").replace(/\s+/g, " ").trim();
14087
- }
14088
- function normalizeComparableMessageContent(text) {
14089
- const lines = String(text || "").split(/\r\n|\n|\r/g).map((line) => line.trim()).filter(Boolean);
14090
- if (lines.length === 0) return "";
14091
- if (shouldReflowComparableMessageLines(lines)) {
14092
- return joinComparableMessageLines(lines);
14093
- }
14094
- return lines.join(" ").replace(/\s+/g, " ").trim();
14095
- }
14096
- function trimPromptEchoPrefix(text, promptText) {
14097
- const prompt2 = normalizeComparableMessageContent(String(promptText || ""));
14098
- if (!prompt2) return String(text || "");
14099
- const lines = String(text || "").split(/\r\n|\n|\r/g);
14100
- let dropCount = 0;
14101
- for (let index = 0; index < Math.min(lines.length, 6); index += 1) {
14102
- const fragment = normalizeComparableMessageContent(lines[index].replace(/^[.…]+\s*/, ""));
14103
- if (!fragment) {
14104
- if (dropCount === index) dropCount = index + 1;
14105
- continue;
14106
- }
14107
- const fragmentWordCount = fragment ? fragment.split(/\s+/).filter(Boolean).length : 0;
14108
- const canBePromptEcho = fragment.length >= 16 || fragmentWordCount >= 4;
14109
- if (canBePromptEcho && prompt2.includes(fragment)) {
14110
- dropCount = index + 1;
14111
- continue;
14112
- }
14113
- break;
14114
- }
14115
- return lines.slice(dropCount).join("\n").trim();
14116
- }
14117
- function getLastUserPromptText(messages) {
14118
- const items = Array.isArray(messages) ? messages : [];
14119
- for (let index = items.length - 1; index >= 0; index -= 1) {
14120
- const message = items[index];
14121
- if (message?.role === "user" && typeof message.content === "string" && message.content.trim()) {
14122
- return message.content;
14123
- }
14124
- }
14125
- return "";
14126
- }
14127
13823
  function parsePatternEntry(x) {
14128
13824
  if (x instanceof RegExp) return x;
14129
13825
  if (x && typeof x === "object" && typeof x.source === "string") {
@@ -14150,7 +13846,7 @@ function normalizeCliProviderForRuntime(raw) {
14150
13846
  }
14151
13847
  };
14152
13848
  }
14153
- var os12, path14, import_child_process4, buildCliSpawnEnv, COMMON_COMPARABLE_WRAP_WORDS;
13849
+ var os12, path14, import_child_process4, buildCliSpawnEnv;
14154
13850
  var init_provider_cli_shared = __esm({
14155
13851
  "../../oss/packages/daemon-core/src/cli-adapters/provider-cli-shared.ts"() {
14156
13852
  "use strict";
@@ -14159,32 +13855,6 @@ var init_provider_cli_shared = __esm({
14159
13855
  import_child_process4 = require("child_process");
14160
13856
  init_spawn_env();
14161
13857
  buildCliSpawnEnv = sanitizeSpawnEnv;
14162
- COMMON_COMPARABLE_WRAP_WORDS = /* @__PURE__ */ new Set([
14163
- "a",
14164
- "an",
14165
- "and",
14166
- "as",
14167
- "at",
14168
- "but",
14169
- "by",
14170
- "for",
14171
- "from",
14172
- "in",
14173
- "into",
14174
- "is",
14175
- "it",
14176
- "of",
14177
- "on",
14178
- "or",
14179
- "that",
14180
- "the",
14181
- "their",
14182
- "then",
14183
- "this",
14184
- "to",
14185
- "was",
14186
- "with"
14187
- ]);
14188
13858
  }
14189
13859
  });
14190
13860
 
@@ -14195,169 +13865,8 @@ function sliceFromOffset(text, start) {
14195
13865
  if (start >= text.length) return "";
14196
13866
  return text.slice(start);
14197
13867
  }
14198
- function hydrateCliParsedMessages(parsedMessages, options) {
14199
- const { committedMessages, scope, lastOutputAt } = options;
14200
- const referenceMessages = [...committedMessages];
14201
- const referenceComparables = new Array(referenceMessages.length);
14202
- const usedReferenceIndexes = /* @__PURE__ */ new Set();
14203
- const now = options.now ?? Date.now();
14204
- let exactReferenceIndexesByKey = null;
14205
- const exactReferenceCursorByKey = /* @__PURE__ */ new Map();
14206
- const hasFiniteTimestamp = (message) => typeof message?.timestamp === "number" && Number.isFinite(message.timestamp);
14207
- const getReferenceComparable = (index) => {
14208
- if (typeof referenceComparables[index] === "string") return referenceComparables[index] || "";
14209
- const comparable = normalizeComparableMessageContent(referenceMessages[index]?.content || "");
14210
- referenceComparables[index] = comparable;
14211
- return comparable;
14212
- };
14213
- const messagesShareStableIdentity = (parsed, reference) => {
14214
- if (!parsed || !reference) return false;
14215
- const parsedId = typeof parsed.id === "string" ? parsed.id.trim() : "";
14216
- const referenceId = typeof reference.id === "string" ? reference.id.trim() : "";
14217
- if (parsedId && referenceId && parsedId === referenceId) return true;
14218
- return typeof parsed.index === "number" && Number.isFinite(parsed.index) && typeof reference.index === "number" && Number.isFinite(reference.index) && parsed.index === reference.index;
14219
- };
14220
- const exactReferenceKey = (role, comparable) => `${role}\0${comparable}`;
14221
- const ensureExactReferenceIndex = () => {
14222
- if (exactReferenceIndexesByKey) return exactReferenceIndexesByKey;
14223
- const byKey = /* @__PURE__ */ new Map();
14224
- for (let i = 0; i < referenceMessages.length; i++) {
14225
- const candidate = referenceMessages[i];
14226
- if (!candidate || candidate.role !== "user" && candidate.role !== "assistant" || !hasFiniteTimestamp(candidate)) continue;
14227
- const comparable = getReferenceComparable(i);
14228
- if (!comparable) continue;
14229
- const key = exactReferenceKey(candidate.role, comparable);
14230
- const indexes = byKey.get(key);
14231
- if (indexes) {
14232
- indexes.push(i);
14233
- } else {
14234
- byKey.set(key, [i]);
14235
- }
14236
- }
14237
- exactReferenceIndexesByKey = byKey;
14238
- return byKey;
14239
- };
14240
- const takeExactReferenceTimestamp = (role, normalizedContent) => {
14241
- const key = exactReferenceKey(role, normalizedContent);
14242
- const indexes = ensureExactReferenceIndex().get(key);
14243
- if (!indexes) return void 0;
14244
- let cursor = exactReferenceCursorByKey.get(key) || 0;
14245
- while (cursor < indexes.length) {
14246
- const candidateIndex = indexes[cursor];
14247
- cursor += 1;
14248
- if (usedReferenceIndexes.has(candidateIndex)) continue;
14249
- const candidate = referenceMessages[candidateIndex];
14250
- if (!candidate || candidate.role !== role || !hasFiniteTimestamp(candidate)) continue;
14251
- usedReferenceIndexes.add(candidateIndex);
14252
- exactReferenceCursorByKey.set(key, cursor);
14253
- return candidate.timestamp;
14254
- }
14255
- exactReferenceCursorByKey.set(key, cursor);
14256
- return void 0;
14257
- };
14258
- const findReferenceTimestamp = (message, role, content, parsedIndex) => {
14259
- const sameIndex = referenceMessages[parsedIndex];
14260
- if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && hasFiniteTimestamp(sameIndex) && messagesShareStableIdentity(message, sameIndex)) {
14261
- usedReferenceIndexes.add(parsedIndex);
14262
- return sameIndex.timestamp;
14263
- }
14264
- const normalizedContent = normalizeComparableMessageContent(content);
14265
- if (!normalizedContent) return void 0;
14266
- if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && getReferenceComparable(parsedIndex) === normalizedContent && hasFiniteTimestamp(sameIndex)) {
14267
- usedReferenceIndexes.add(parsedIndex);
14268
- return sameIndex.timestamp;
14269
- }
14270
- const exactTimestamp = takeExactReferenceTimestamp(role, normalizedContent);
14271
- if (typeof exactTimestamp === "number") return exactTimestamp;
14272
- for (let i = 0; i < referenceMessages.length; i++) {
14273
- if (usedReferenceIndexes.has(i)) continue;
14274
- const candidate = referenceMessages[i];
14275
- if (!candidate || candidate.role !== role) continue;
14276
- const candidateContent = getReferenceComparable(i);
14277
- if (!candidateContent) continue;
14278
- const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
14279
- if (!fuzzyMatch) continue;
14280
- if (hasFiniteTimestamp(candidate)) {
14281
- usedReferenceIndexes.add(i);
14282
- return candidate.timestamp;
14283
- }
14284
- }
14285
- return void 0;
14286
- };
14287
- return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message, index) => {
14288
- const role = message.role;
14289
- const content = typeof message.content === "string" ? message.content : String(message.content || "");
14290
- const parsedTimestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0;
14291
- const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(message, role, content, index);
14292
- const fallbackTimestamp = role === "user" ? scope?.startedAt || now : lastOutputAt || scope?.startedAt || now;
14293
- const timestamp = referenceTimestamp ?? fallbackTimestamp;
14294
- return {
14295
- ...message,
14296
- role,
14297
- content,
14298
- timestamp,
14299
- receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp
14300
- };
14301
- });
14302
- }
14303
- function chooseMoreComparableCliMessage(left2, right2, leftComparable = normalizeComparableMessageContent(left2.content || ""), rightComparable = normalizeComparableMessageContent(right2.content || "")) {
14304
- if (leftComparable && leftComparable === rightComparable) {
14305
- const leftNewlines = String(left2.content || "").split(/\r\n|\n|\r/g).length - 1;
14306
- const rightNewlines = String(right2.content || "").split(/\r\n|\n|\r/g).length - 1;
14307
- return rightNewlines < leftNewlines ? right2 : left2;
14308
- }
14309
- return rightComparable.length > leftComparable.length ? right2 : left2;
14310
- }
14311
- function dedupeConsecutiveComparableCliMessages(messages) {
14312
- const deduped = [];
14313
- for (const message of messages) {
14314
- const current = {
14315
- ...message,
14316
- content: typeof message.content === "string" ? message.content : String(message.content || "")
14317
- };
14318
- const currentComparable = normalizeComparableMessageContent(current.content || "");
14319
- const previous = deduped[deduped.length - 1];
14320
- if (!previous) {
14321
- deduped.push({ message: current, comparable: currentComparable });
14322
- continue;
14323
- }
14324
- const sameRole = previous.message.role === current.role;
14325
- const sameKind = (previous.message.kind || "standard") === (current.kind || "standard");
14326
- const sameSender = (previous.message.senderName || "") === (current.senderName || "");
14327
- const comparableMatch = previous.comparable && previous.comparable === currentComparable;
14328
- if (sameRole && sameKind && sameSender && comparableMatch) {
14329
- const selected = chooseMoreComparableCliMessage(
14330
- previous.message,
14331
- current,
14332
- previous.comparable,
14333
- currentComparable
14334
- );
14335
- deduped[deduped.length - 1] = {
14336
- message: selected,
14337
- comparable: selected === current ? currentComparable : previous.comparable
14338
- };
14339
- continue;
14340
- }
14341
- deduped.push({ message: current, comparable: currentComparable });
14342
- }
14343
- return deduped.map((entry) => entry.message);
14344
- }
14345
- function normalizeCliParsedMessages(parsedMessages, options) {
14346
- return dedupeConsecutiveComparableCliMessages(hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
14347
- role: message.role,
14348
- content: message.content,
14349
- timestamp: message.timestamp,
14350
- receivedAt: message.receivedAt,
14351
- kind: message.kind,
14352
- id: message.id,
14353
- index: message.index,
14354
- providerUnitKey: message.providerUnitKey,
14355
- bubbleId: message.bubbleId,
14356
- bubbleState: message.bubbleState,
14357
- _turnKey: message._turnKey,
14358
- meta: message.meta,
14359
- senderName: message.senderName
14360
- })));
13868
+ function normalizeCliParsedMessages(parsedMessages, _options) {
13869
+ return Array.isArray(parsedMessages) ? parsedMessages : [];
14361
13870
  }
14362
13871
  function buildCliParseInput(options) {
14363
13872
  const {
@@ -14567,40 +14076,8 @@ var provider_cli_adapter_exports = {};
14567
14076
  __export(provider_cli_adapter_exports, {
14568
14077
  ProviderCliAdapter: () => ProviderCliAdapter,
14569
14078
  appendBoundedText: () => appendBoundedText,
14570
- normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime,
14571
- sanitizeCliStandardMessageContent: () => sanitizeCliStandardMessageContent,
14572
- trimLastAssistantEchoForCliMessages: () => trimLastAssistantEchoForCliMessages
14573
- });
14574
- function normalizeComparableTranscriptText(value) {
14575
- return sanitizeTerminalText(String(value || "")).replace(/\s+/g, " ").trim();
14576
- }
14577
- function hasVisibleInterruptPrompt(text) {
14578
- const interruptCopyPattern = /\bEnter\s+to\s+interrupt\b(?:\s*,?\s*Ctrl\s*(?:\+|-)?\s*C\s+to\s+cancel)?/i;
14579
- return sanitizeTerminalText(text || "").split(/\r?\n/g).some((line) => {
14580
- const trimmed = line.trim();
14581
- if (!interruptCopyPattern.test(trimmed)) return false;
14582
- return /^(?:[^A-Za-z0-9\s]{1,8}\s+)?[❯›>]\s+/.test(trimmed);
14583
- });
14584
- }
14585
- function parsedTranscriptIsRicherThanCommitted(parsedMessages, committedMessages) {
14586
- if (!Array.isArray(parsedMessages) || !Array.isArray(committedMessages)) return false;
14587
- if (parsedMessages.length > committedMessages.length) return true;
14588
- if (parsedMessages.length !== committedMessages.length) return false;
14589
- for (let index = 0; index < parsedMessages.length; index += 1) {
14590
- const parsed = parsedMessages[index];
14591
- const committed = committedMessages[index];
14592
- if (!parsed || !committed) return false;
14593
- if ((parsed.role || "") !== (committed.role || "")) return false;
14594
- if (parsed.id && committed.id && String(parsed.id) !== String(committed.id)) return false;
14595
- if (typeof parsed.index === "number" && typeof committed.index === "number" && parsed.index !== committed.index) return false;
14596
- const parsedText = normalizeComparableTranscriptText(parsed.content);
14597
- const committedText = normalizeComparableTranscriptText(committed.content);
14598
- if (!parsedText || !committedText || parsedText === committedText) continue;
14599
- if (parsedText.length > committedText.length && parsedText.startsWith(committedText)) return true;
14600
- return false;
14601
- }
14602
- return false;
14603
- }
14079
+ normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
14080
+ });
14604
14081
  function appendBoundedText(current, chunk, maxChars) {
14605
14082
  if (!chunk) return current.length <= maxChars ? current : current.slice(-maxChars);
14606
14083
  if (maxChars <= 0) return "";
@@ -14609,76 +14086,7 @@ function appendBoundedText(current, chunk, maxChars) {
14609
14086
  if (current.length <= keepFromCurrent) return current + chunk;
14610
14087
  return current.slice(-keepFromCurrent) + chunk;
14611
14088
  }
14612
- function isLikelyCommittedActivityPrefixContinuation(line) {
14613
- const trimmed = String(line || "").trim();
14614
- if (!trimmed) return false;
14615
- if (COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(trimmed)) return false;
14616
- if (/\s/.test(trimmed)) return false;
14617
- if (/[가-힣]/.test(trimmed)) return false;
14618
- if (trimmed.length > 96) return false;
14619
- return /^[A-Za-z0-9_./:@+%=-]+$/.test(trimmed);
14620
- }
14621
- function parseCommittedActivityPrefixBlock(lines, index) {
14622
- const first = String(lines[index] || "").trim();
14623
- if (!COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(first)) return null;
14624
- const parts = [first];
14625
- let nextIndex = index + 1;
14626
- while (nextIndex < lines.length && isLikelyCommittedActivityPrefixContinuation(lines[nextIndex])) {
14627
- parts.push(String(lines[nextIndex] || "").trim());
14628
- nextIndex += 1;
14629
- }
14630
- return { label: parts.join(""), nextIndex };
14631
- }
14632
- function sanitizeCliStandardMessageContent(content) {
14633
- const source = String(content || "").trim();
14634
- if (!source) return "";
14635
- const lines = source.split(/\r?\n/);
14636
- if (lines.length < 4) return source;
14637
- const counts = /* @__PURE__ */ new Map();
14638
- for (let index = 0; index < lines.length; index += 1) {
14639
- const block = parseCommittedActivityPrefixBlock(lines, index);
14640
- if (!block) continue;
14641
- counts.set(block.label, (counts.get(block.label) || 0) + 1);
14642
- index = block.nextIndex - 1;
14643
- }
14644
- const repeatedLabels = new Set(
14645
- Array.from(counts.entries()).filter(([, count]) => count >= 3).map(([label]) => label)
14646
- );
14647
- if (repeatedLabels.size === 0) return source;
14648
- const stripped = [];
14649
- let removed = 0;
14650
- for (let index = 0; index < lines.length; index += 1) {
14651
- const block = parseCommittedActivityPrefixBlock(lines, index);
14652
- if (block && repeatedLabels.has(block.label)) {
14653
- removed += 1;
14654
- index = block.nextIndex - 1;
14655
- continue;
14656
- }
14657
- stripped.push(lines[index]);
14658
- }
14659
- const next = stripped.join("\n").replace(/\n{3,}/g, "\n\n").trim();
14660
- return removed >= 3 && next.length >= 80 ? next : source;
14661
- }
14662
- function sanitizeCommittedMessageForDisplay(message) {
14663
- if (!message || message.role !== "assistant" || (message.kind || "standard") !== "standard") return message;
14664
- const content = sanitizeCliStandardMessageContent(message.content);
14665
- if (content === message.content) return message;
14666
- return { ...message, content };
14667
- }
14668
- function trimLastAssistantEchoForCliMessages(messages, prompt2) {
14669
- if (!prompt2) return;
14670
- for (let index = messages.length - 1; index >= 0; index -= 1) {
14671
- const message = messages[index];
14672
- if (!message || message.role !== "assistant" || typeof message.content !== "string") continue;
14673
- if ((message.kind || "standard") !== "standard") continue;
14674
- message.content = trimPromptEchoPrefix(message.content, prompt2);
14675
- if (!message.content.trim()) {
14676
- messages.splice(index, 1);
14677
- }
14678
- return;
14679
- }
14680
- }
14681
- var os14, COMMITTED_ACTIVITY_PREFIX_BLOCK_RE, ProviderCliAdapter;
14089
+ var os14, ProviderCliAdapter;
14682
14090
  var init_provider_cli_adapter = __esm({
14683
14091
  "../../oss/packages/daemon-core/src/cli-adapters/provider-cli-adapter.ts"() {
14684
14092
  "use strict";
@@ -14688,13 +14096,10 @@ var init_provider_cli_adapter = __esm({
14688
14096
  init_terminal_screen();
14689
14097
  init_pty_transport();
14690
14098
  init_provider_cli_shared();
14691
- init_chat_message_normalization();
14692
- init_read_chat_contract();
14693
14099
  init_provider_cli_parse();
14694
14100
  init_provider_cli_config();
14695
14101
  init_provider_cli_runtime();
14696
14102
  init_provider_cli_shared();
14697
- COMMITTED_ACTIVITY_PREFIX_BLOCK_RE = /^(?:📖|💻|🔎|📚|📋|✏️|📝|🔧|🛠️|⚙️)\s+(.+)$/;
14698
14103
  ProviderCliAdapter = class _ProviderCliAdapter {
14699
14104
  constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
14700
14105
  this.extraArgs = extraArgs;
@@ -14737,11 +14142,6 @@ var init_provider_cli_adapter = __esm({
14737
14142
  provider;
14738
14143
  ptyProcess = null;
14739
14144
  transportFactory;
14740
- messages = [];
14741
- committedMessages = [];
14742
- structuredMessages = [];
14743
- committedMessagesActivitySignature = "";
14744
- committedMessagesChangedAt = 0;
14745
14145
  currentStatus = "starting";
14746
14146
  onStatusChange = null;
14747
14147
  responseBuffer = "";
@@ -14821,11 +14221,8 @@ var init_provider_cli_adapter = __esm({
14821
14221
  traceSeq = 0;
14822
14222
  traceSessionId = "";
14823
14223
  parsedStatusCache = null;
14824
- lastStatusHotPathParseAt = Number.NEGATIVE_INFINITY;
14825
- static STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS = 1e3;
14826
14224
  static SCREEN_SNAPSHOT_MIN_INTERVAL_MS = 250;
14827
14225
  static MAX_TRACE_ENTRIES = 250;
14828
- static PARSE_MESSAGE_TAIL_LIMIT = 100;
14829
14226
  providerResolutionMeta;
14830
14227
  static FINISH_RETRY_DELAY_MS = 300;
14831
14228
  static MAX_FINISH_RETRIES = 2;
@@ -14846,35 +14243,6 @@ var init_provider_cli_adapter = __esm({
14846
14243
  recordBoundedAppendDrop(previousLength, appendedLength, nextLength) {
14847
14244
  return Math.max(0, previousLength + appendedLength - nextLength);
14848
14245
  }
14849
- buildCommittedMessagesActivitySignature() {
14850
- const last = this.committedMessages[this.committedMessages.length - 1];
14851
- return [
14852
- String(this.committedMessages.length),
14853
- String(last?.role || ""),
14854
- String(last?.kind || ""),
14855
- String(last?.senderName || ""),
14856
- String(last?.timestamp || ""),
14857
- String(last?.receivedAt || ""),
14858
- normalizeComparableMessageContent(last?.content || "").slice(-240)
14859
- ].join("|");
14860
- }
14861
- syncMessageViews() {
14862
- const signature = this.buildCommittedMessagesActivitySignature();
14863
- if (signature !== this.committedMessagesActivitySignature) {
14864
- this.committedMessagesActivitySignature = signature;
14865
- this.committedMessagesChangedAt = Date.now();
14866
- }
14867
- this.messages = [...this.committedMessages];
14868
- this.structuredMessages = [...this.committedMessages];
14869
- }
14870
- getLastCommittedMessageActivityAt() {
14871
- const last = this.committedMessages[this.committedMessages.length - 1];
14872
- const messageTime = Math.max(
14873
- typeof last?.receivedAt === "number" && Number.isFinite(last.receivedAt) ? last.receivedAt : 0,
14874
- typeof last?.timestamp === "number" && Number.isFinite(last.timestamp) ? last.timestamp : 0
14875
- );
14876
- return Math.max(messageTime, this.committedMessagesChangedAt || 0);
14877
- }
14878
14246
  readTerminalScreenText(now = Date.now()) {
14879
14247
  const screenText = this.terminalScreen.getText() || "";
14880
14248
  this.lastScreenText = screenText;
@@ -14894,7 +14262,7 @@ var init_provider_cli_adapter = __esm({
14894
14262
  }
14895
14263
  getFreshParsedStatusCache() {
14896
14264
  const cached2 = this.parsedStatusCache;
14897
- 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) {
14898
14266
  return cached2.result;
14899
14267
  }
14900
14268
  return null;
@@ -14905,45 +14273,6 @@ var init_provider_cli_adapter = __esm({
14905
14273
  shouldUseFullProviderTranscriptContext() {
14906
14274
  return this.providerOwnsTranscript() && this.provider.transcriptContext === "full";
14907
14275
  }
14908
- selectParseBaseMessages(baseMessages) {
14909
- if (this.shouldUseFullProviderTranscriptContext()) return baseMessages;
14910
- if (baseMessages.length <= _ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
14911
- return baseMessages.slice(-_ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
14912
- }
14913
- messagesShareStableIdentity(left2, right2) {
14914
- if (left2 === right2) return true;
14915
- if (!left2 || !right2) return false;
14916
- if ((left2.role || "") !== (right2.role || "")) return false;
14917
- if (left2.id && right2.id && String(left2.id) === String(right2.id)) return true;
14918
- if (typeof left2.index === "number" && typeof right2.index === "number" && left2.index === right2.index) return true;
14919
- return false;
14920
- }
14921
- messagesComparable(left2, right2) {
14922
- if (this.messagesShareStableIdentity(left2, right2)) return true;
14923
- if (!left2 || !right2) return false;
14924
- if ((left2.role || "") !== (right2.role || "")) return false;
14925
- const leftText = normalizeComparableTranscriptText(left2.content);
14926
- const rightText = normalizeComparableTranscriptText(right2.content);
14927
- return !!leftText && leftText === rightText;
14928
- }
14929
- stitchParsedMessagesWithCommittedBase(parsedMessages, fullBaseMessages, parseBaseMessages) {
14930
- if (!Array.isArray(parsedMessages) || parsedMessages.length === 0) return parsedMessages;
14931
- if (fullBaseMessages.length <= parseBaseMessages.length) return parsedMessages;
14932
- const parsedFirst = parsedMessages[0];
14933
- const fullFirst = fullBaseMessages[0];
14934
- if (parsedMessages.length >= fullBaseMessages.length && this.messagesComparable(parsedFirst, fullFirst)) {
14935
- return parsedMessages;
14936
- }
14937
- const tailFirst = parseBaseMessages[0];
14938
- if (tailFirst && this.messagesComparable(parsedFirst, tailFirst)) {
14939
- const prefixLength = fullBaseMessages.length - parseBaseMessages.length;
14940
- const prefix = fullBaseMessages.slice(0, prefixLength);
14941
- const shouldSanitizePrefix = !!this.currentTurnScope || this.currentStatus !== "idle" || !!this.activeModal;
14942
- const nextPrefix = shouldSanitizePrefix ? prefix.map((message) => sanitizeCommittedMessageForDisplay(message)) : prefix;
14943
- return [...nextPrefix, ...parsedMessages];
14944
- }
14945
- return [...fullBaseMessages, ...parsedMessages];
14946
- }
14947
14276
  getIdleFinishConfirmMs() {
14948
14277
  return this.timeouts.idleFinishConfirm;
14949
14278
  }
@@ -15396,9 +14725,6 @@ var init_provider_cli_adapter = __esm({
15396
14725
  `[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(summarizeCliTraceText(finalScreenText, 240)).slice(0, 280)}`
15397
14726
  );
15398
14727
  }
15399
- trimLastAssistantEcho(messages, prompt2) {
15400
- trimLastAssistantEchoForCliMessages(messages, prompt2);
15401
- }
15402
14728
  clearAllTimers() {
15403
14729
  if (this.responseTimeout) {
15404
14730
  clearTimeout(this.responseTimeout);
@@ -15494,10 +14820,10 @@ var init_provider_cli_adapter = __esm({
15494
14820
  }
15495
14821
  const session = this.runParseSession();
15496
14822
  if (!session) return;
15497
- const { status, messages, modal, parsedStatus } = session;
14823
+ const { status, messages, parsedStatus } = session;
14824
+ const modal = session.activeModal ?? session.modal ?? null;
15498
14825
  const parsedMessages = normalizeCliParsedMessages(messages, {
15499
- committedMessages: this.committedMessages,
15500
- scope: this.currentTurnScope,
14826
+ scope: null,
15501
14827
  lastOutputAt: this.lastOutputAt
15502
14828
  });
15503
14829
  if (this.maybeCommitVisibleIdleTranscript(session, parsedMessages)) return;
@@ -15677,7 +15003,7 @@ var init_provider_cli_adapter = __esm({
15677
15003
  const effectiveScreenText = screenText || this.accumulatedBuffer;
15678
15004
  const noActiveTurn = !this.currentTurnScope;
15679
15005
  const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(effectiveScreenText);
15680
- const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant && parsedMessages.length > this.committedMessages.length;
15006
+ const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant;
15681
15007
  if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
15682
15008
  return;
15683
15009
  }
@@ -15834,10 +15160,7 @@ var init_provider_cli_adapter = __esm({
15834
15160
  }
15835
15161
  const visibleAssistant = [...parsedMessages].reverse().find((m) => m.role === "assistant" && m.content.trim());
15836
15162
  if (!visibleAssistant) return false;
15837
- this.committedMessages = parsedMessages;
15838
- this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
15839
15163
  this.clearAllTimers();
15840
- this.syncMessageViews();
15841
15164
  this.responseBuffer = "";
15842
15165
  this.isWaitingForResponse = false;
15843
15166
  this.responseSettleIgnoreUntil = 0;
@@ -15849,37 +15172,34 @@ var init_provider_cli_adapter = __esm({
15849
15172
  this.setStatus("idle", "script_idle_commit");
15850
15173
  this.onStatusChange?.();
15851
15174
  this.recordTrace("script_idle_commit", {
15852
- messageCount: this.committedMessages.length,
15175
+ messageCount: parsedMessages.length,
15853
15176
  lastAssistant: summarizeCliTraceText(visibleAssistant.content, 320)
15854
15177
  });
15855
15178
  return true;
15856
15179
  }
15857
15180
  commitCurrentTranscript() {
15858
15181
  const parsed = this.parseCurrentTranscript(
15859
- this.committedMessages,
15182
+ [],
15860
15183
  this.responseBuffer,
15861
15184
  this.currentTurnScope
15862
15185
  );
15863
15186
  if (parsed && Array.isArray(parsed.messages)) {
15864
- this.committedMessages = normalizeCliParsedMessages(parsed.messages, {
15865
- committedMessages: this.committedMessages,
15866
- scope: this.currentTurnScope,
15187
+ const parsedMessages = normalizeCliParsedMessages(parsed.messages, {
15188
+ scope: null,
15867
15189
  lastOutputAt: this.lastOutputAt
15868
15190
  });
15869
- this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
15870
- this.syncMessageViews();
15871
- const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
15191
+ const lastAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
15872
15192
  if (this.currentTurnScope) {
15873
15193
  LOG.info(
15874
15194
  "CLI",
15875
- `[${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)}`
15876
15196
  );
15877
15197
  }
15878
15198
  this.recordTrace("commit_transcript", {
15879
15199
  parsedStatus: parsed.status || null,
15880
- messageCount: this.committedMessages.length,
15200
+ messageCount: parsedMessages.length,
15881
15201
  lastAssistant: lastAssistant ? summarizeCliTraceText(lastAssistant.content, 320) : "",
15882
- messages: summarizeCliTraceMessages(this.committedMessages),
15202
+ messages: summarizeCliTraceMessages(parsedMessages),
15883
15203
  ...buildCliTraceParseSnapshot({
15884
15204
  accumulatedBuffer: this.accumulatedBuffer,
15885
15205
  accumulatedRawBuffer: this.accumulatedRawBuffer,
@@ -15913,63 +15233,31 @@ var init_provider_cli_adapter = __esm({
15913
15233
  }
15914
15234
  // ─── Script Execution ──────────────────────────
15915
15235
  runParseSession() {
15916
- if (typeof this.cliScripts?.parseSession === "function") {
15917
- try {
15918
- const screenText = this.terminalScreen.getText();
15919
- const tail = this.recentOutputBuffer.slice(-500);
15920
- const parseBaseMessages = this.selectParseBaseMessages(this.committedMessages);
15921
- const input = buildCliParseInput({
15922
- accumulatedBuffer: this.accumulatedBuffer,
15923
- accumulatedRawBuffer: this.accumulatedRawBuffer,
15924
- recentOutputBuffer: this.recentOutputBuffer,
15925
- terminalScreenText: screenText,
15926
- baseMessages: parseBaseMessages,
15927
- partialResponse: this.responseBuffer,
15928
- isWaitingForResponse: this.isWaitingForResponse,
15929
- scope: this.currentTurnScope,
15930
- runtimeSettings: this.runtimeSettings
15931
- });
15932
- const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
15933
- if (session && typeof session === "object" && Array.isArray(session.messages)) {
15934
- session.messages = this.stitchParsedMessagesWithCommittedBase(
15935
- session.messages,
15936
- this.committedMessages,
15937
- parseBaseMessages
15938
- );
15939
- }
15940
- this.parseErrorMessage = null;
15941
- return session && typeof session === "object" ? session : null;
15942
- } catch (e) {
15943
- const message = e?.message || String(e);
15944
- this.parseErrorMessage = message;
15945
- LOG.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
15946
- return null;
15947
- }
15236
+ if (typeof this.cliScripts?.parseSession !== "function") {
15237
+ this.parseErrorMessage = `${this.cliType} parseSession unavailable`;
15238
+ return null;
15948
15239
  }
15949
- if (!this.cliScripts?.detectStatus && !this.cliScripts?.parseOutput) return null;
15950
15240
  try {
15951
- const tail = this.settledBuffer;
15952
- const parsedTranscript = this.parseCurrentTranscript(
15953
- this.committedMessages,
15954
- this.responseBuffer,
15955
- this.currentTurnScope
15956
- );
15957
- const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((b) => typeof b === "string" && b.trim()) ? parsedTranscript.activeModal : null;
15958
- const approval = this.runParseApproval(tail);
15959
- const modal = approval || parsedModal;
15960
- const rawStatus = this.runDetectStatus(tail);
15961
- const parsedStatus = typeof parsedTranscript?.status === "string" ? parsedTranscript.status : null;
15962
- const effectiveStatus = parsedStatus === "waiting_approval" && modal ? "waiting_approval" : rawStatus || parsedStatus || "idle";
15963
- return {
15964
- status: effectiveStatus,
15965
- messages: Array.isArray(parsedTranscript?.messages) ? parsedTranscript.messages : [],
15966
- modal,
15967
- parsedStatus
15968
- };
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;
15969
15257
  } catch (e) {
15970
15258
  const message = e?.message || String(e);
15971
15259
  this.parseErrorMessage = message;
15972
- LOG.warn("CLI", `[${this.cliType}] parseSession fallback error: ${message}`);
15260
+ LOG.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
15973
15261
  return null;
15974
15262
  }
15975
15263
  }
@@ -16019,45 +15307,14 @@ var init_provider_cli_adapter = __esm({
16019
15307
  if (this.isWaitingForResponse && this.currentTurnScope && this.currentStatus !== "stopped") return "generating";
16020
15308
  return this.currentStatus;
16021
15309
  }
16022
- suppressStaleParsedApproval(parsed, recentBuffer, screenText) {
16023
- const actionableParsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
16024
- if (!parsed || parsed?.status !== "waiting_approval" || !actionableParsedModal) {
16025
- return parsed;
16026
- }
16027
- const inApprovalCooldown = this.lastApprovalResolvedAt > 0 && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
16028
- if (!inApprovalCooldown) {
16029
- return parsed;
16030
- }
16031
- const visibleModal = this.runParseApproval(recentBuffer);
16032
- if (visibleModal) {
16033
- return parsed;
16034
- }
16035
- const detectedStatus = this.runDetectStatus(recentBuffer);
16036
- const resolvedStatus = detectedStatus && detectedStatus !== "waiting_approval" ? detectedStatus : this.isWaitingForResponse || this.currentTurnScope ? "generating" : this.currentStatus === "waiting_approval" ? "idle" : this.currentStatus;
16037
- return {
16038
- ...parsed,
16039
- status: resolvedStatus,
16040
- activeModal: null
16041
- };
16042
- }
16043
15310
  // ─── Public API (CliAdapter) ───────────────────
16044
15311
  getStatus(options = {}) {
16045
15312
  const allowParse = options.allowParse !== false;
16046
15313
  const startupModal = allowParse && this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
16047
15314
  let effectiveStatus = this.projectEffectiveStatus(startupModal);
16048
15315
  let effectiveModal = startupModal || this.activeModal;
16049
- if (allowParse && !startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
16050
- let parsed = this.getFreshParsedStatusCache();
16051
- if (!parsed && effectiveStatus !== "idle") {
16052
- const now = Date.now();
16053
- if (now - this.lastStatusHotPathParseAt >= _ProviderCliAdapter.STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS) {
16054
- this.lastStatusHotPathParseAt = now;
16055
- try {
16056
- parsed = this.getScriptParsedStatus();
16057
- } catch {
16058
- }
16059
- }
16060
- }
15316
+ if (allowParse && !startupModal && !effectiveModal) {
15317
+ const parsed = this.getFreshParsedStatusCache();
16061
15318
  const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
16062
15319
  if (parsed?.status === "waiting_approval" && parsedModal) {
16063
15320
  effectiveStatus = "waiting_approval";
@@ -16067,7 +15324,7 @@ var init_provider_cli_adapter = __esm({
16067
15324
  const bufferState = this.getBufferState();
16068
15325
  return {
16069
15326
  status: effectiveStatus,
16070
- messages: [...this.committedMessages],
15327
+ messages: [],
16071
15328
  workingDir: this.workingDir,
16072
15329
  activeModal: effectiveModal,
16073
15330
  errorMessage: this.parseErrorMessage || void 0,
@@ -16075,98 +15332,6 @@ var init_provider_cli_adapter = __esm({
16075
15332
  ...bufferState ? { bufferState } : {}
16076
15333
  };
16077
15334
  }
16078
- seedCommittedMessages(messages) {
16079
- const normalized = (Array.isArray(messages) ? messages : []).filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
16080
- role: message.role,
16081
- content: typeof message.content === "string" ? message.content : String(message.content || ""),
16082
- timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0,
16083
- receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : void 0,
16084
- kind: typeof message.kind === "string" ? message.kind : void 0,
16085
- id: typeof message.id === "string" ? message.id : void 0,
16086
- index: typeof message.index === "number" ? message.index : void 0,
16087
- providerUnitKey: typeof message.providerUnitKey === "string" ? message.providerUnitKey : void 0,
16088
- bubbleId: typeof message.bubbleId === "string" ? message.bubbleId : void 0,
16089
- bubbleState: typeof message.bubbleState === "string" ? message.bubbleState : void 0,
16090
- _turnKey: typeof message._turnKey === "string" ? message._turnKey : void 0,
16091
- meta: message.meta && typeof message.meta === "object" ? { ...message.meta } : void 0,
16092
- senderName: typeof message.senderName === "string" ? message.senderName : void 0
16093
- }));
16094
- this.committedMessages = normalized;
16095
- this.syncMessageViews();
16096
- }
16097
- getSharedCommittedPrefixLength(parsedMessages) {
16098
- const committedMessages = this.committedMessages;
16099
- const max = Math.min(parsedMessages.length, committedMessages.length);
16100
- let index = 0;
16101
- while (index < max && this.messagesShareStableIdentity(parsedMessages[index], committedMessages[index])) {
16102
- index += 1;
16103
- }
16104
- return index;
16105
- }
16106
- hydrateCommittedPrefixForParsedStatus(parsedMessages) {
16107
- const sharedPrefixLength = this.getSharedCommittedPrefixLength(parsedMessages);
16108
- if (sharedPrefixLength !== this.committedMessages.length) return null;
16109
- const committedHydratedMessages = this.committedMessages.map((message, index) => {
16110
- const timestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : this.lastOutputAt || this.currentTurnScope?.startedAt || Date.now();
16111
- const contentValue = message.content;
16112
- return {
16113
- role: message.role,
16114
- content: typeof contentValue === "string" ? contentValue : String(contentValue || ""),
16115
- timestamp,
16116
- receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp,
16117
- kind: message.kind,
16118
- id: message.id || `msg_${index}`,
16119
- index: typeof message.index === "number" ? message.index : index,
16120
- providerUnitKey: message.providerUnitKey,
16121
- bubbleId: message.bubbleId,
16122
- bubbleState: message.bubbleState,
16123
- _turnKey: message._turnKey,
16124
- meta: message.meta,
16125
- senderName: message.senderName
16126
- };
16127
- });
16128
- const extraMessages = parsedMessages.slice(sharedPrefixLength);
16129
- if (extraMessages.length === 0) return committedHydratedMessages;
16130
- const extraHydratedMessages = hydrateCliParsedMessages(extraMessages, {
16131
- committedMessages: [],
16132
- scope: this.currentTurnScope,
16133
- lastOutputAt: this.lastOutputAt
16134
- }).map((message, offset) => ({
16135
- ...message,
16136
- id: message.id || `msg_${sharedPrefixLength + offset}`,
16137
- index: typeof message.index === "number" ? message.index : sharedPrefixLength + offset
16138
- }));
16139
- return [...committedHydratedMessages, ...extraHydratedMessages];
16140
- }
16141
- hydrateParsedMessagesForStatus(parsedMessages) {
16142
- return this.hydrateCommittedPrefixForParsedStatus(parsedMessages) || hydrateCliParsedMessages(parsedMessages, {
16143
- committedMessages: this.committedMessages,
16144
- scope: this.currentTurnScope,
16145
- lastOutputAt: this.lastOutputAt
16146
- });
16147
- }
16148
- buildCommittedChatMessages() {
16149
- return this.committedMessages.map((message, index) => {
16150
- const rawContentValue = message.content;
16151
- const rawContent = typeof rawContentValue === "string" ? rawContentValue : String(rawContentValue || "");
16152
- const content = message.role === "assistant" && (message.kind || "standard") === "standard" ? sanitizeCliStandardMessageContent(rawContent) : rawContent;
16153
- return buildChatMessage({
16154
- role: message.role,
16155
- content,
16156
- timestamp: message.timestamp,
16157
- kind: message.kind,
16158
- meta: message.meta,
16159
- senderName: message.senderName,
16160
- id: message.id || `msg_${index}`,
16161
- index: typeof message.index === "number" ? message.index : index,
16162
- providerUnitKey: message.providerUnitKey,
16163
- bubbleId: message.bubbleId,
16164
- bubbleState: message.bubbleState,
16165
- _turnKey: message._turnKey,
16166
- receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
16167
- });
16168
- });
16169
- }
16170
15335
  /**
16171
15336
  * Script-based full parse — returns ReadChatResult.
16172
15337
  * Called by command handler / dashboard for rich content rendering.
@@ -16174,125 +15339,30 @@ var init_provider_cli_adapter = __esm({
16174
15339
  getScriptParsedStatus() {
16175
15340
  const screenText = this.readTerminalScreenText();
16176
15341
  const cached2 = this.parsedStatusCache;
16177
- 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) {
16178
15343
  return cached2.result;
16179
15344
  }
16180
- const parsed = this.parseCurrentTranscript(
16181
- this.committedMessages,
16182
- this.responseBuffer,
16183
- this.currentTurnScope,
16184
- screenText
16185
- );
16186
- const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
16187
- if (parsedModal && parsed?.status === "waiting_approval") {
16188
- this.activeModal = parsedModal;
16189
- this.isWaitingForResponse = true;
16190
- if (this.currentStatus !== "waiting_approval") {
16191
- this.setStatus("waiting_approval", "parsed_waiting_approval");
16192
- this.onStatusChange?.();
16193
- }
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`);
16194
15348
  }
16195
- if (parsed && Array.isArray(parsed.messages) && this.provider.allowInputDuringGeneration === true) {
16196
- const hydratedForCommit = normalizeCliParsedMessages(parsed.messages, {
16197
- committedMessages: this.committedMessages,
16198
- 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,
16199
15357
  lastOutputAt: this.lastOutputAt
16200
- });
16201
- const fakeSession = {
16202
- status: parsed.status || "idle",
16203
- messages: parsed.messages,
16204
- modal: parsedModal,
16205
- parsedStatus: parsed.status || null
16206
- };
16207
- if (this.maybeCommitVisibleIdleTranscript(fakeSession, hydratedForCommit)) {
16208
- return this.getScriptParsedStatus();
16209
- }
16210
- }
16211
- const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
16212
- let result;
16213
- if (parsed && Array.isArray(parsed.messages)) {
16214
- const parsedHydratedMessages = this.hydrateParsedMessagesForStatus(parsed.messages);
16215
- const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === "assistant" && typeof message.content === "string" && message.content.trim());
16216
- 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");
16217
- if (shouldAdoptParsedIdleReplay) {
16218
- this.committedMessages = this.getSharedCommittedPrefixLength(parsed.messages) === this.committedMessages.length ? parsedHydratedMessages.map((message) => ({
16219
- role: message.role,
16220
- content: typeof message.content === "string" ? message.content : String(message.content || ""),
16221
- timestamp: message.timestamp,
16222
- receivedAt: message.receivedAt,
16223
- kind: message.kind,
16224
- id: message.id,
16225
- index: message.index,
16226
- meta: message.meta,
16227
- senderName: message.senderName
16228
- })) : normalizeCliParsedMessages(parsed.messages, {
16229
- committedMessages: this.committedMessages,
16230
- scope: this.currentTurnScope,
16231
- lastOutputAt: this.lastOutputAt
16232
- });
16233
- this.syncMessageViews();
16234
- if (this.currentStatus !== "idle" || this.isWaitingForResponse) {
16235
- this.responseBuffer = "";
16236
- this.isWaitingForResponse = false;
16237
- this.responseSettleIgnoreUntil = 0;
16238
- this.submitRetryUsed = false;
16239
- this.submitRetryPromptSnippet = "";
16240
- this.finishRetryCount = 0;
16241
- this.currentTurnScope = null;
16242
- this.activeModal = null;
16243
- this.setStatus("idle", "parsed_idle_replay_commit");
16244
- this.onStatusChange?.();
16245
- }
16246
- }
16247
- const shouldPreferCommittedHistoryReplay = !this.currentTurnScope && !this.activeModal && this.committedMessages.length > parsedHydratedMessages.length;
16248
- const shouldPreferCommittedIdleReplay = shouldPreferCommittedMessages && !shouldAdoptParsedIdleReplay;
16249
- const hydratedMessages = shouldPreferCommittedIdleReplay || shouldPreferCommittedHistoryReplay ? this.buildCommittedChatMessages() : parsedHydratedMessages;
16250
- result = {
16251
- id: parsed.id || "cli_session",
16252
- status: parsed.status || this.currentStatus,
16253
- title: parsed.title || this.cliName,
16254
- messages: hydratedMessages,
16255
- activeModal: parsed.activeModal ?? this.activeModal,
16256
- providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
16257
- ...this.getBufferState() ? { bufferState: this.getBufferState() } : {},
16258
- ...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
16259
- };
16260
- } else {
16261
- const messages = [...this.committedMessages];
16262
- const bufferState = this.getBufferState();
16263
- result = {
16264
- id: "cli_session",
16265
- status: this.currentStatus,
16266
- title: this.cliName,
16267
- messages: messages.map((message, index) => buildChatMessage({
16268
- ...message,
16269
- id: message.id || `msg_${index}`,
16270
- index: typeof message.index === "number" ? message.index : index,
16271
- receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
16272
- })),
16273
- activeModal: this.activeModal,
16274
- ...bufferState ? { bufferState } : {}
16275
- };
16276
- }
16277
- const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
16278
- const shouldClampStaleGeneratingToIdle = result?.status === "generating" && this.currentStatus === "idle" && !this.currentTurnScope && !result?.activeModal && hasVisibleAssistantMessage && !hasVisibleInterruptPrompt(screenText);
16279
- if (shouldClampStaleGeneratingToIdle) {
16280
- result = {
16281
- ...result,
16282
- status: "idle",
16283
- messages: Array.isArray(result.messages) ? result.messages.map((message) => {
16284
- if (message?.role !== "assistant" || !message?.meta?.streaming) return message;
16285
- const nextMeta = { ...message.meta || {} };
16286
- delete nextMeta.streaming;
16287
- return {
16288
- ...message,
16289
- ...Object.keys(nextMeta).length > 0 ? { meta: nextMeta } : { meta: void 0 }
16290
- };
16291
- }) : result.messages
16292
- };
16293
- }
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
+ };
16294
15365
  this.parsedStatusCache = {
16295
- committedMessagesRef: this.committedMessages,
16296
15366
  responseBuffer: this.responseBuffer,
16297
15367
  currentTurnScope: this.currentTurnScope,
16298
15368
  recentOutputBuffer: this.recentOutputBuffer,
@@ -16315,7 +15385,7 @@ var init_provider_cli_adapter = __esm({
16315
15385
  accumulatedRawBuffer: this.accumulatedRawBuffer,
16316
15386
  recentOutputBuffer: this.recentOutputBuffer,
16317
15387
  terminalScreenText: this.terminalScreen.getText(),
16318
- baseMessages: this.committedMessages,
15388
+ baseMessages: [],
16319
15389
  partialResponse: this.responseBuffer,
16320
15390
  isWaitingForResponse: this.isWaitingForResponse,
16321
15391
  scope: this.currentTurnScope,
@@ -16326,46 +15396,8 @@ var init_provider_cli_adapter = __esm({
16326
15396
  args: args && typeof args === "object" ? { ...args } : {}
16327
15397
  }));
16328
15398
  }
16329
- parseCurrentTranscript(baseMessages, partialResponse, scope, screenTextOverride) {
16330
- if (!this.cliScripts?.parseOutput) {
16331
- this.parseErrorMessage = null;
16332
- return null;
16333
- }
16334
- try {
16335
- const screenText = typeof screenTextOverride === "string" ? screenTextOverride : this.terminalScreen.getText();
16336
- const parseBaseMessages = this.selectParseBaseMessages(baseMessages);
16337
- const input = buildCliParseInput({
16338
- accumulatedBuffer: this.accumulatedBuffer,
16339
- accumulatedRawBuffer: this.accumulatedRawBuffer,
16340
- recentOutputBuffer: this.recentOutputBuffer,
16341
- terminalScreenText: screenText,
16342
- baseMessages: parseBaseMessages,
16343
- partialResponse,
16344
- isWaitingForResponse: this.isWaitingForResponse,
16345
- scope,
16346
- runtimeSettings: this.runtimeSettings
16347
- });
16348
- const parsed = this.cliScripts.parseOutput(input);
16349
- if (parsed && typeof parsed === "object") {
16350
- Object.assign(parsed, validateReadChatResultPayload(parsed, `${this.cliType} parseOutput`));
16351
- }
16352
- const normalizedParsed = this.suppressStaleParsedApproval(parsed, input.recentBuffer, input.screenText);
16353
- if (normalizedParsed && Array.isArray(normalizedParsed.messages)) {
16354
- normalizedParsed.messages = this.stitchParsedMessagesWithCommittedBase(
16355
- normalizedParsed.messages,
16356
- baseMessages,
16357
- parseBaseMessages
16358
- );
16359
- this.trimLastAssistantEcho(normalizedParsed.messages, scope?.prompt || getLastUserPromptText(baseMessages));
16360
- }
16361
- this.parseErrorMessage = null;
16362
- return normalizedParsed;
16363
- } catch (e) {
16364
- const message = e?.message || String(e);
16365
- this.parseErrorMessage = message;
16366
- LOG.warn("CLI", `[${this.cliType}] parseOutput error: ${message}`);
16367
- throw e;
16368
- }
15399
+ parseCurrentTranscript(_baseMessages, _partialResponse, _scope, _screenTextOverride) {
15400
+ return this.runParseSession();
16369
15401
  }
16370
15402
  /** Whether this adapter has CLI scripts loaded */
16371
15403
  hasCliScripts() {
@@ -16427,8 +15459,6 @@ var init_provider_cli_adapter = __esm({
16427
15459
  commitSendUserTurn(state) {
16428
15460
  if (state.didCommitUserTurn) return;
16429
15461
  state.didCommitUserTurn = true;
16430
- this.committedMessages.push({ role: "user", content: state.text, timestamp: Date.now() });
16431
- this.syncMessageViews();
16432
15462
  }
16433
15463
  armResponseTimeout() {
16434
15464
  if (this.responseTimeout) clearTimeout(this.responseTimeout);
@@ -16620,11 +15650,6 @@ var init_provider_cli_adapter = __esm({
16620
15650
  }
16621
15651
  })() : null;
16622
15652
  const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
16623
- const parsedMessagesBeforeSend = Array.isArray(parsedStatusBeforeSend?.messages) ? parsedStatusBeforeSend.messages.filter((message) => message && (message.role === "user" || message.role === "assistant")) : [];
16624
- const shouldCommitParsedIdleBeforeSend = !allowInputDuringGeneration && parsedSessionStatus === "idle" && parsedMessagesBeforeSend.length > this.committedMessages.length && parsedMessagesBeforeSend.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
16625
- if (shouldCommitParsedIdleBeforeSend) {
16626
- this.commitCurrentTranscript();
16627
- }
16628
15653
  if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
16629
15654
  throw new Error(`${this.cliName} is still processing the previous prompt`);
16630
15655
  }
@@ -16730,9 +15755,6 @@ var init_provider_cli_adapter = __esm({
16730
15755
  activeModal: this.activeModal,
16731
15756
  parseErrorMessage: this.parseErrorMessage,
16732
15757
  messageCounts: {
16733
- committed: this.committedMessages.length,
16734
- structured: this.structuredMessages.length,
16735
- visible: this.messages.length,
16736
15758
  parsedCache: Array.isArray(parsedResult?.messages) ? parsedResult.messages.length : void 0
16737
15759
  },
16738
15760
  buffers: {
@@ -16783,8 +15805,7 @@ var init_provider_cli_adapter = __esm({
16783
15805
  responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
16784
15806
  responseEpoch: this.responseEpoch,
16785
15807
  resizeSuppressUntil: this.resizeSuppressUntil,
16786
- lastApprovalResolvedAt: this.lastApprovalResolvedAt,
16787
- committedMessagesChangedAt: this.committedMessagesChangedAt
15808
+ lastApprovalResolvedAt: this.lastApprovalResolvedAt
16788
15809
  },
16789
15810
  finish: {
16790
15811
  idleFinishCandidate: this.idleFinishCandidate,
@@ -16909,8 +15930,6 @@ var init_provider_cli_adapter = __esm({
16909
15930
  }
16910
15931
  clearHistory() {
16911
15932
  this.clearIdleFinishCandidate("clear_history");
16912
- this.committedMessages = [];
16913
- this.syncMessageViews();
16914
15933
  this.accumulatedBuffer = "";
16915
15934
  this.accumulatedRawBuffer = "";
16916
15935
  this.currentTurnScope = null;
@@ -16951,7 +15970,7 @@ var init_provider_cli_adapter = __esm({
16951
15970
  }
16952
15971
  resolveModal(buttonIndex) {
16953
15972
  let modal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
16954
- if (!modal && typeof this.cliScripts?.parseOutput === "function") {
15973
+ if (!modal && typeof this.cliScripts?.parseSession === "function") {
16955
15974
  try {
16956
15975
  const parsed = this.getScriptParsedStatus();
16957
15976
  const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
@@ -17018,10 +16037,8 @@ var init_provider_cli_adapter = __esm({
17018
16037
  startupParseGate: this.startupParseGate,
17019
16038
  spawnAt: this.spawnAt,
17020
16039
  workingDir: this.workingDir,
17021
- messages: this.messages,
17022
- committedMessages: this.committedMessages,
17023
- structuredMessages: this.structuredMessages,
17024
- messageCount: this.committedMessages.length,
16040
+ messages: [],
16041
+ messageCount: 0,
17025
16042
  screenText: screenText.slice(-4e3),
17026
16043
  currentTurnScope: this.currentTurnScope,
17027
16044
  startupBuffer: this.startupBuffer.slice(-4e3),
@@ -17073,7 +16090,7 @@ var init_provider_cli_adapter = __esm({
17073
16090
  lifecycleStatus: this.isWaitingForResponse ? "awaiting_response" : "idle",
17074
16091
  activeModal: this.activeModal,
17075
16092
  currentTurnScope: this.currentTurnScope,
17076
- messages: summarizeCliTraceMessages(this.committedMessages, 5)
16093
+ messages: []
17077
16094
  };
17078
16095
  }
17079
16096
  getProviderResolutionMeta() {
@@ -17366,17 +16383,11 @@ var init_cli_provider_instance = __esm({
17366
16383
  }
17367
16384
  const runtime = this.adapter.getRuntimeMetadata();
17368
16385
  this.maybeAppendRuntimeRecoveryMessage(runtime);
17369
- 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 : [];
17370
16387
  const historyMessageCount = Number.isFinite(parsedStatus?.historyMessageCount) ? Math.max(0, Number(parsedStatus.historyMessageCount)) : null;
17371
16388
  if (historyMessageCount !== null) {
17372
16389
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
17373
16390
  }
17374
- const committedMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
17375
- const isActiveNonIdle = adapterStatus.status !== "idle";
17376
- const shouldApplyCommittedFloor = parsedMessages.length < committedMessages.length && (adapterStatus.status === "waiting_approval" || isActiveNonIdle && historyMessageCount === null);
17377
- if (shouldApplyCommittedFloor) {
17378
- parsedMessages = normalizeChatMessages(committedMessages);
17379
- }
17380
16391
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
17381
16392
  const canonicalBackedHistory = this.syncCanonicalSavedHistoryIfNeeded();
17382
16393
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
@@ -17469,11 +16480,9 @@ var init_cli_provider_instance = __esm({
17469
16480
  const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
17470
16481
  const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
17471
16482
  const runtime = this.adapter.getRuntimeMetadata();
17472
- const lastCommittedMessageActivityAt = typeof this.adapter.getLastCommittedMessageActivityAt === "function" ? this.adapter.getLastCommittedMessageActivityAt() : 0;
17473
16483
  return {
17474
16484
  id: this.instanceId,
17475
16485
  status: visibleStatus,
17476
- lastMessageAt: lastCommittedMessageActivityAt || void 0,
17477
16486
  runtimeLifecycle: runtime?.lifecycle ?? null,
17478
16487
  runtimeSurfaceKind: runtime?.surfaceKind,
17479
16488
  runtimeRestoredFromStorage: runtime?.restoredFromStorage === true,
@@ -17579,7 +16588,7 @@ var init_cli_provider_instance = __esm({
17579
16588
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
17580
16589
  const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
17581
16590
  const partial2 = this.adapter.getPartialResponse();
17582
- const progressFingerprint = newStatus === "generating" ? `${partial2 || ""}::${adapterStatus.messages.at(-1)?.content || ""}`.slice(-2e3) : void 0;
16591
+ const progressFingerprint = newStatus === "generating" ? `${partial2 || ""}`.slice(-2e3) : void 0;
17583
16592
  const previousStatus = this.lastStatus;
17584
16593
  if (newStatus !== this.lastStatus) {
17585
16594
  LOG.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
@@ -18025,18 +17034,6 @@ ${effect.notification.body || ""}`.trim();
18025
17034
  receivedAt: message.receivedAt
18026
17035
  }));
18027
17036
  this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
18028
- if (restoredHistory.messages.length > 0) {
18029
- this.adapter.seedCommittedMessages(
18030
- restoredHistory.messages.map((message) => ({
18031
- role: message.role,
18032
- content: message.content,
18033
- timestamp: message.receivedAt,
18034
- receivedAt: message.receivedAt,
18035
- kind: message.kind,
18036
- senderName: message.senderName
18037
- }))
18038
- );
18039
- }
18040
17037
  }
18041
17038
  getProbeDirectories() {
18042
17039
  const dirs = /* @__PURE__ */ new Set();
@@ -40264,13 +39261,24 @@ async function launchWithCdp(options = {}) {
40264
39261
  break;
40265
39262
  }
40266
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
+ }
40267
39275
  return {
40268
39276
  success: true,
40269
39277
  ideId: targetIde.id,
40270
39278
  ideName: targetIde.displayName,
40271
39279
  port,
40272
39280
  action: alreadyRunning ? "restarted" : "started",
40273
- 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}`
40274
39282
  };
40275
39283
  } catch (e) {
40276
39284
  return {
@@ -42267,9 +41275,6 @@ var init_ipc_protocol = __esm({
42267
41275
  });
42268
41276
 
42269
41277
  // ../../oss/packages/daemon-core/src/chat/subscription-updates.ts
42270
- function normalizeSyncMode(syncMode) {
42271
- return syncMode === "append" || syncMode === "replace_tail" || syncMode === "noop" || syncMode === "full" ? syncMode : "full";
42272
- }
42273
41278
  function normalizeModalButtons(value) {
42274
41279
  return Array.isArray(value) ? value.filter((button) => typeof button === "string") : [];
42275
41280
  }
@@ -42296,55 +41301,39 @@ function normalizeSessionModalFields(activeModal) {
42296
41301
  modalButtons: normalizeModalButtons(activeModal.buttons)
42297
41302
  };
42298
41303
  }
42299
- function buildNextChatCursor(cursor, result) {
42300
- return {
42301
- knownMessageCount: Math.max(0, Number(result.totalMessages || cursor.knownMessageCount)),
42302
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : cursor.lastMessageSignature,
42303
- tailLimit: cursor.tailLimit
42304
- };
42305
- }
42306
41304
  function prepareSessionChatTailUpdate(input) {
42307
41305
  const result = input.result;
42308
- if (!result?.success || result.syncMode === "noop") {
41306
+ if (!result?.success) {
42309
41307
  return {
42310
- cursor: result?.success ? buildNextChatCursor(input.cursor, result) : input.cursor,
41308
+ cursor: input.cursor,
42311
41309
  seq: input.seq,
42312
41310
  lastDeliveredSignature: input.lastDeliveredSignature,
42313
41311
  update: null
42314
41312
  };
42315
41313
  }
42316
- const syncMode = normalizeSyncMode(result.syncMode);
42317
- const cursor = {
42318
- knownMessageCount: Math.max(0, Number(result.totalMessages || 0)),
42319
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : "",
42320
- tailLimit: input.cursor.tailLimit
42321
- };
41314
+ const messages = Array.isArray(result.messages) ? result.messages : [];
42322
41315
  const title = typeof result.title === "string" ? result.title : void 0;
42323
41316
  const activeModal = normalizeChatTailActiveModal(result.activeModal);
42324
41317
  const status = typeof result.status === "string" ? result.status : "idle";
42325
41318
  const deliverySignature = buildChatTailDeliverySignature({
42326
41319
  sessionId: input.sessionId,
42327
41320
  ...input.historySessionId ? { historySessionId: input.historySessionId } : {},
42328
- messages: Array.isArray(result.messages) ? result.messages : [],
41321
+ messages,
42329
41322
  status,
42330
41323
  ...title ? { title } : {},
42331
- ...activeModal ? { activeModal } : {},
42332
- syncMode,
42333
- replaceFrom: Number(result.replaceFrom || 0),
42334
- totalMessages: Number(result.totalMessages || 0),
42335
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
41324
+ ...activeModal ? { activeModal } : {}
42336
41325
  });
42337
41326
  const seq = input.seq + 1;
42338
41327
  if (deliverySignature === input.lastDeliveredSignature) {
42339
41328
  return {
42340
- cursor,
41329
+ cursor: input.cursor,
42341
41330
  seq,
42342
41331
  lastDeliveredSignature: input.lastDeliveredSignature,
42343
41332
  update: null
42344
41333
  };
42345
41334
  }
42346
41335
  return {
42347
- cursor,
41336
+ cursor: input.cursor,
42348
41337
  seq,
42349
41338
  lastDeliveredSignature: deliverySignature,
42350
41339
  update: {
@@ -42355,14 +41344,10 @@ function prepareSessionChatTailUpdate(input) {
42355
41344
  ...input.interactionId ? { interactionId: input.interactionId } : {},
42356
41345
  seq,
42357
41346
  timestamp: input.timestamp,
42358
- messages: Array.isArray(result.messages) ? result.messages : [],
41347
+ messages,
42359
41348
  status,
42360
41349
  ...title ? { title } : {},
42361
- ...activeModal ? { activeModal } : {},
42362
- syncMode,
42363
- replaceFrom: Number(result.replaceFrom || 0),
42364
- totalMessages: Number(result.totalMessages || 0),
42365
- lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
41350
+ ...activeModal ? { activeModal } : {}
42366
41351
  }
42367
41352
  };
42368
41353
  }
@@ -47100,7 +46085,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
47100
46085
  lines.push("Provider category: `cli`");
47101
46086
  lines.push("");
47102
46087
  const funcToFile = {
47103
- parseOutput: "parse_output.js",
46088
+ parseSession: "parse_session.js",
47104
46089
  detectStatus: "detect_status.js",
47105
46090
  parseApproval: "parse_approval.js"
47106
46091
  };
@@ -47189,7 +46174,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
47189
46174
  lines.push("");
47190
46175
  lines.push("| Function | Input | Return |");
47191
46176
  lines.push("|---|---|---|");
47192
- 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 }` |");
47193
46178
  lines.push("| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |");
47194
46179
  lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
47195
46180
  lines.push("");
@@ -47409,7 +46394,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
47409
46394
  lines.push("");
47410
46395
  lines.push("## Required Validation");
47411
46396
  lines.push("1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.");
47412
- 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.");
47413
46398
  lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
47414
46399
  lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
47415
46400
  lines.push("5. Confirm the Python file was actually created and executed, not just described in chat text.");
@@ -48708,7 +47693,7 @@ var init_dev_server = __esm({
48708
47693
  lines.push("Provider category: `cli`");
48709
47694
  lines.push("");
48710
47695
  const funcToFile = {
48711
- parseOutput: "parse_output.js",
47696
+ parseSession: "parse_session.js",
48712
47697
  detectStatus: "detect_status.js",
48713
47698
  parseApproval: "parse_approval.js"
48714
47699
  };
@@ -48797,7 +47782,7 @@ var init_dev_server = __esm({
48797
47782
  lines.push("");
48798
47783
  lines.push("| Function | Input | Return |");
48799
47784
  lines.push("|---|---|---|");
48800
- 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 }` |");
48801
47786
  lines.push("| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |");
48802
47787
  lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
48803
47788
  lines.push("");
@@ -48892,7 +47877,7 @@ var init_dev_server = __esm({
48892
47877
  lines.push("");
48893
47878
  lines.push("## Required Validation");
48894
47879
  lines.push("1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.");
48895
- 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.");
48896
47881
  lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
48897
47882
  lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
48898
47883
  lines.push("5. Confirm the Python file was actually created and executed, not just described in chat text.");
@@ -81684,8 +80669,6 @@ function handleSubscribe(peerId, msg, peers, handlers) {
81684
80669
  params,
81685
80670
  seq: 0,
81686
80671
  cursor: {
81687
- knownMessageCount: Math.max(0, Number(params.knownMessageCount || 0)),
81688
- lastMessageSignature: typeof params.lastMessageSignature === "string" ? params.lastMessageSignature : "",
81689
80672
  tailLimit: Math.max(0, Number(params.tailLimit || 0))
81690
80673
  },
81691
80674
  lastDeliveredSignature: ""
@@ -82725,12 +81708,8 @@ ${e?.stack || ""}`);
82725
81708
  sessionId: subscription.params.targetSessionId,
82726
81709
  seq: subscription.seq,
82727
81710
  timestamp: Date.now(),
82728
- syncMode: "noop",
82729
81711
  messages: [],
82730
81712
  status: "",
82731
- replaceFrom: 0,
82732
- totalMessages: 0,
82733
- lastMessageSignature: "",
82734
81713
  error: error48?.message || "chat_tail build failed"
82735
81714
  };
82736
81715
  this.screenshotSender.sendTopicUpdateToPeer(peer, errorUpdate);
@@ -90413,7 +89392,7 @@ var init_adhdev_daemon = __esm({
90413
89392
  init_version();
90414
89393
  init_src();
90415
89394
  init_runtime_defaults();
90416
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.64" });
89395
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.66" });
90417
89396
  AdhdevDaemon = class _AdhdevDaemon {
90418
89397
  localHttpServer = null;
90419
89398
  localWss = null;
@@ -90573,8 +89552,6 @@ var init_adhdev_daemon = __esm({
90573
89552
  const result = await this.components.router.execute("read_chat", {
90574
89553
  targetSessionId: subscription.params.targetSessionId,
90575
89554
  ...subscription.params.historySessionId ? { historySessionId: subscription.params.historySessionId } : {},
90576
- knownMessageCount: subscription.cursor.knownMessageCount,
90577
- lastMessageSignature: subscription.cursor.lastMessageSignature,
90578
89555
  ...subscription.cursor.tailLimit > 0 ? { tailLimit: subscription.cursor.tailLimit } : {}
90579
89556
  }, "p2p");
90580
89557
  const interactionId = this.getSessionInteractionId(subscription.params.targetSessionId);
@@ -90602,9 +89579,7 @@ var init_adhdev_daemon = __esm({
90602
89579
  level: "info",
90603
89580
  sessionId: subscription.params.targetSessionId,
90604
89581
  payload: {
90605
- syncMode: prepared.update.syncMode,
90606
- totalMessages: prepared.update.totalMessages,
90607
- replaceFrom: prepared.update.replaceFrom,
89582
+ returnedMessages: prepared.update.messages.length,
90608
89583
  hasModal: !!prepared.update.activeModal,
90609
89584
  hasTitle: typeof prepared.update.title === "string"
90610
89585
  }