adhdev 0.8.83 → 0.8.85

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
@@ -7682,6 +7682,7 @@ function normalizeReadChatCommandStatus(status, activeModal) {
7682
7682
  }
7683
7683
  function buildReadChatCommandResult(payload, args) {
7684
7684
  let validatedPayload;
7685
+ const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
7685
7686
  try {
7686
7687
  validatedPayload = validateReadChatResultPayload({
7687
7688
  ...payload,
@@ -7702,7 +7703,8 @@ function buildReadChatCommandResult(payload, args) {
7702
7703
  syncMode: "full",
7703
7704
  replaceFrom: 0,
7704
7705
  totalMessages: messages.length,
7705
- lastMessageSignature
7706
+ lastMessageSignature,
7707
+ ...debugReadChat ? { debugReadChat } : {}
7706
7708
  };
7707
7709
  }
7708
7710
  const sync = computeReadChatSync(messages, cursor);
@@ -7713,7 +7715,8 @@ function buildReadChatCommandResult(payload, args) {
7713
7715
  syncMode: sync.syncMode,
7714
7716
  replaceFrom: sync.replaceFrom,
7715
7717
  totalMessages: sync.totalMessages,
7716
- lastMessageSignature: sync.lastMessageSignature
7718
+ lastMessageSignature: sync.lastMessageSignature,
7719
+ ...debugReadChat ? { debugReadChat } : {}
7717
7720
  };
7718
7721
  }
7719
7722
  function didProviderConfirmSend(result) {
@@ -7804,14 +7807,33 @@ async function handleReadChat(h, args) {
7804
7807
  }
7805
7808
  }
7806
7809
  const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
7807
- const status = parsedRecord || adapter.getStatus();
7810
+ const adapterStatus = adapter.getStatus();
7811
+ const shouldPreferAdapterMessages = Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
7812
+ const status = parsedRecord ? {
7813
+ ...parsedRecord,
7814
+ messages: shouldPreferAdapterMessages ? adapterStatus.messages : parsedRecord.messages,
7815
+ status: adapterStatus.status !== "idle" ? adapterStatus.status : parsedRecord.status || adapterStatus.status,
7816
+ activeModal: parsedRecord.activeModal || adapterStatus.activeModal
7817
+ } : adapterStatus;
7808
7818
  const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
7809
7819
  const providerSessionId = typeof parsedRecord?.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
7810
7820
  if (status) {
7821
+ LOG.info("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}`);
7811
7822
  return buildReadChatCommandResult({
7812
7823
  messages: status.messages || [],
7813
7824
  status: status.status,
7814
7825
  activeModal: status.activeModal,
7826
+ debugReadChat: {
7827
+ provider: adapter.cliType,
7828
+ targetSessionId: String(args?.targetSessionId || ""),
7829
+ adapterStatus: String(adapterStatus.status || ""),
7830
+ parsedStatus: String(parsedRecord?.status || ""),
7831
+ returnedStatus: String(status.status || ""),
7832
+ shouldPreferAdapterMessages,
7833
+ adapterMsgCount: Array.isArray(adapterStatus.messages) ? adapterStatus.messages.length : 0,
7834
+ parsedMsgCount: Array.isArray(parsedRecord?.messages) ? parsedRecord.messages.length : 0,
7835
+ returnedMsgCount: Array.isArray(status.messages) ? status.messages.length : 0
7836
+ },
7815
7837
  ...title ? { title } : {},
7816
7838
  ...providerSessionId ? { providerSessionId } : {}
7817
7839
  }, args);
@@ -12734,6 +12756,58 @@ var init_provider_cli_adapter = __esm({
12734
12756
  `[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(summarizeCliTraceText(finalScreenText, 240)).slice(0, 280)}`
12735
12757
  );
12736
12758
  }
12759
+ clearStaleIdleResponseGuard(reason) {
12760
+ const screenText = this.terminalScreen.getText() || "";
12761
+ const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
12762
+ const blockingModal = this.activeModal || this.getStartupConfirmationModal(screenText);
12763
+ if (!this.isWaitingForResponse || this.currentStatus !== "idle" || !visibleIdlePrompt || !!blockingModal) {
12764
+ return false;
12765
+ }
12766
+ if (this.responseTimeout) {
12767
+ clearTimeout(this.responseTimeout);
12768
+ this.responseTimeout = null;
12769
+ }
12770
+ if (this.idleTimeout) {
12771
+ clearTimeout(this.idleTimeout);
12772
+ this.idleTimeout = null;
12773
+ }
12774
+ if (this.approvalExitTimeout) {
12775
+ clearTimeout(this.approvalExitTimeout);
12776
+ this.approvalExitTimeout = null;
12777
+ }
12778
+ if (this.finishRetryTimer) {
12779
+ clearTimeout(this.finishRetryTimer);
12780
+ this.finishRetryTimer = null;
12781
+ }
12782
+ this.clearIdleFinishCandidate(reason);
12783
+ this.responseBuffer = "";
12784
+ this.isWaitingForResponse = false;
12785
+ this.responseSettleIgnoreUntil = 0;
12786
+ this.submitRetryUsed = false;
12787
+ this.submitRetryPromptSnippet = "";
12788
+ this.finishRetryCount = 0;
12789
+ this.currentTurnScope = null;
12790
+ this.activeModal = null;
12791
+ this.recordTrace("stale_idle_response_cleared", {
12792
+ reason,
12793
+ screenText: summarizeCliTraceText(screenText, 240)
12794
+ });
12795
+ return true;
12796
+ }
12797
+ hasMeaningfulResponseBuffer(promptSnippet) {
12798
+ const raw = String(this.responseBuffer || "").trim();
12799
+ if (!raw) return false;
12800
+ const normalizedPrompt = compactPromptText(promptSnippet);
12801
+ if (!normalizedPrompt) return true;
12802
+ const normalizedBuffer = compactPromptText(raw);
12803
+ if (!normalizedBuffer) return false;
12804
+ if (normalizedBuffer === normalizedPrompt) return false;
12805
+ if (normalizedBuffer.startsWith(normalizedPrompt)) {
12806
+ const remainder = normalizedBuffer.slice(normalizedPrompt.length).replace(/[─═\-]+/g, "").replace(/⏵⏵accepteditson\([^)]*\)/gi, "").replace(/accepteditson\([^)]*\)/gi, "").replace(/(?:◐|◑|◒|◓|◔|◕|◉|●|·)?(?:x?high|medium|low|max)·?\/effort/gi, "").replace(/updateavailable!run:[a-z0-9:._\-/]+/gi, "").replace(/esctointerrupt/gi, "").replace(/❯/g, "").replace(/^[\s\-–—:;,.!/?]+/, "").trim();
12807
+ return remainder.length > 0;
12808
+ }
12809
+ return true;
12810
+ }
12737
12811
  evaluateSettled() {
12738
12812
  const now = Date.now();
12739
12813
  if (this.submitPendingUntil > now || this.responseSettleIgnoreUntil > now) {
@@ -12766,7 +12840,11 @@ var init_provider_cli_adapter = __esm({
12766
12840
  scope: this.currentTurnScope,
12767
12841
  lastOutputAt: this.lastOutputAt
12768
12842
  }) : [];
12843
+ if (this.maybeCommitVisibleIdleTranscript(parsedTranscript)) {
12844
+ return;
12845
+ }
12769
12846
  const lastParsedAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
12847
+ const normalizedPromptSnippet = normalizePromptText(this.submitRetryPromptSnippet || this.currentTurnScope?.prompt || "");
12770
12848
  this.recordTrace("settled", {
12771
12849
  tail: summarizeCliTraceText(tail, 500),
12772
12850
  screenText: summarizeCliTraceText(screenText, 1200),
@@ -12784,6 +12862,24 @@ var init_provider_cli_adapter = __esm({
12784
12862
  scope: this.currentTurnScope
12785
12863
  })
12786
12864
  });
12865
+ if (this.currentTurnScope && !lastParsedAssistant && !this.submitRetryUsed && this.ptyProcess && this.currentStatus !== "waiting_approval" && promptLikelyVisible(screenText, normalizedPromptSnippet) && !this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) {
12866
+ this.submitRetryUsed = true;
12867
+ this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
12868
+ LOG.info("CLI", `[${this.cliType}] Retrying submit key from settled parser (no assistant yet)`);
12869
+ this.recordTrace("submit_write", {
12870
+ mode: "settled_retry",
12871
+ sendKey: this.sendKey,
12872
+ screenText: summarizeCliTraceText(screenText, 500)
12873
+ });
12874
+ this.ptyProcess.write(this.sendKey);
12875
+ if (this.settleTimer) clearTimeout(this.settleTimer);
12876
+ this.settleTimer = setTimeout(() => {
12877
+ this.settleTimer = null;
12878
+ this.settledBuffer = this.recentOutputBuffer;
12879
+ this.evaluateSettled();
12880
+ }, this.timeouts.outputSettle + 150);
12881
+ return;
12882
+ }
12787
12883
  if (this.currentTurnScope && !lastParsedAssistant) {
12788
12884
  LOG.info(
12789
12885
  "CLI",
@@ -12826,7 +12922,15 @@ var init_provider_cli_adapter = __esm({
12826
12922
  }
12827
12923
  const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
12828
12924
  const statusActivityHoldMs = this.getStatusActivityHoldMs();
12829
- const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity;
12925
+ const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
12926
+ const visibleAssistantCandidate = this.looksLikeVisibleAssistantCandidate(screenText);
12927
+ if (this.currentTurnScope && this.cliType === "claude-cli") {
12928
+ LOG.info(
12929
+ "CLI",
12930
+ `[${this.cliType}] settled diagnostics prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} scriptStatus=${String(scriptStatus || "")} parsedStatus=${String(parsedTranscript?.status || "")} parsedMsgCount=${parsedMessages.length} lastParsedAssistant=${JSON.stringify(summarizeCliTraceText(lastParsedAssistant?.content || "", 120)).slice(0, 160)} visibleIdlePrompt=${String(visibleIdlePrompt)} visibleAssistantCandidate=${String(visibleAssistantCandidate)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 160)).slice(0, 220)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 160)).slice(0, 220)}`
12931
+ );
12932
+ }
12933
+ const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(visibleIdlePrompt && visibleAssistantCandidate);
12830
12934
  if (shouldHoldGenerating) {
12831
12935
  this.clearIdleFinishCandidate("hold_generating_recent_activity");
12832
12936
  this.setStatus("generating", "recent_activity_hold");
@@ -12857,8 +12961,8 @@ var init_provider_cli_adapter = __esm({
12857
12961
  if (scriptStatus === "waiting_approval") {
12858
12962
  this.clearIdleFinishCandidate("waiting_approval");
12859
12963
  const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
12860
- const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
12861
- if ((inCooldown || visibleIdlePrompt) && !modal) {
12964
+ const visibleIdlePrompt2 = this.looksLikeVisibleIdlePrompt(screenText);
12965
+ if ((inCooldown || visibleIdlePrompt2) && !modal) {
12862
12966
  if (this.approvalExitTimeout) {
12863
12967
  clearTimeout(this.approvalExitTimeout);
12864
12968
  this.approvalExitTimeout = null;
@@ -12930,7 +13034,7 @@ var init_provider_cli_adapter = __esm({
12930
13034
  this.lastApprovalResolvedAt = Date.now();
12931
13035
  }
12932
13036
  if (this.isWaitingForResponse) {
12933
- const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
13037
+ const visibleIdlePrompt2 = this.looksLikeVisibleIdlePrompt(screenText);
12934
13038
  const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
12935
13039
  const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
12936
13040
  const hasAssistantTurn = !!lastParsedAssistant;
@@ -12938,12 +13042,12 @@ var init_provider_cli_adapter = __esm({
12938
13042
  const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
12939
13043
  const idleQuietThresholdMs = Math.max(idleFinishConfirmMs, this.timeouts.outputSettle);
12940
13044
  const idleStableThresholdMs = idleFinishConfirmMs;
12941
- const idleReady = visibleIdlePrompt && !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleStableThresholdMs;
13045
+ const idleReady = visibleIdlePrompt2 && !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleStableThresholdMs;
12942
13046
  const candidate = this.idleFinishCandidate;
12943
13047
  const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= idleFinishConfirmMs;
12944
13048
  const canFinishImmediately = idleReady && candidateQuiet;
12945
13049
  this.recordTrace("idle_decision", {
12946
- visibleIdlePrompt,
13050
+ visibleIdlePrompt: visibleIdlePrompt2,
12947
13051
  quietForMs,
12948
13052
  screenStableMs,
12949
13053
  hasAssistantTurn,
@@ -13063,6 +13167,70 @@ var init_provider_cli_adapter = __esm({
13063
13167
  this.setStatus("idle", "response_finished");
13064
13168
  this.onStatusChange?.();
13065
13169
  }
13170
+ maybeCommitVisibleIdleTranscript(parsed, options) {
13171
+ const allowImmediateScriptIdleCommit = this.provider.allowInputDuringGeneration === true;
13172
+ if (!allowImmediateScriptIdleCommit) return false;
13173
+ if (!parsed || !Array.isArray(parsed.messages) || parsed.status !== "idle" || !this.isWaitingForResponse || !this.currentTurnScope || this.activeModal || parsed.activeModal) {
13174
+ return false;
13175
+ }
13176
+ if (options?.requireVisibleAssistantCandidate) {
13177
+ const candidateText = options.screenText || this.terminalScreen.getText() || "";
13178
+ if (!this.looksLikeVisibleAssistantCandidate(candidateText)) {
13179
+ return false;
13180
+ }
13181
+ }
13182
+ const hydratedForIdleCommit = normalizeCliParsedMessages(parsed.messages, {
13183
+ committedMessages: this.committedMessages,
13184
+ scope: this.currentTurnScope,
13185
+ lastOutputAt: this.lastOutputAt
13186
+ });
13187
+ const visibleAssistant = [...hydratedForIdleCommit].reverse().find((message) => message.role === "assistant" && message.content.trim());
13188
+ if (!visibleAssistant) return false;
13189
+ this.committedMessages = hydratedForIdleCommit;
13190
+ const promptForTrim = this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages);
13191
+ if (promptForTrim) {
13192
+ const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
13193
+ if (lastAssistantForTrim) {
13194
+ lastAssistantForTrim.content = trimPromptEchoPrefix(lastAssistantForTrim.content, promptForTrim);
13195
+ }
13196
+ }
13197
+ if (this.responseTimeout) {
13198
+ clearTimeout(this.responseTimeout);
13199
+ this.responseTimeout = null;
13200
+ }
13201
+ if (this.idleTimeout) {
13202
+ clearTimeout(this.idleTimeout);
13203
+ this.idleTimeout = null;
13204
+ }
13205
+ if (this.approvalExitTimeout) {
13206
+ clearTimeout(this.approvalExitTimeout);
13207
+ this.approvalExitTimeout = null;
13208
+ }
13209
+ if (this.submitRetryTimer) {
13210
+ clearTimeout(this.submitRetryTimer);
13211
+ this.submitRetryTimer = null;
13212
+ }
13213
+ if (this.finishRetryTimer) {
13214
+ clearTimeout(this.finishRetryTimer);
13215
+ this.finishRetryTimer = null;
13216
+ }
13217
+ this.syncMessageViews();
13218
+ this.responseBuffer = "";
13219
+ this.isWaitingForResponse = false;
13220
+ this.responseSettleIgnoreUntil = 0;
13221
+ this.submitRetryUsed = false;
13222
+ this.submitRetryPromptSnippet = "";
13223
+ this.finishRetryCount = 0;
13224
+ this.currentTurnScope = null;
13225
+ this.activeModal = null;
13226
+ this.setStatus("idle", "script_idle_commit");
13227
+ this.onStatusChange?.();
13228
+ this.recordTrace("script_idle_commit", {
13229
+ messageCount: this.committedMessages.length,
13230
+ lastAssistant: summarizeCliTraceText(visibleAssistant.content, 320)
13231
+ });
13232
+ return true;
13233
+ }
13066
13234
  commitCurrentTranscript() {
13067
13235
  const parsed = this.parseCurrentTranscript(
13068
13236
  this.committedMessages,
@@ -13084,6 +13252,12 @@ var init_provider_cli_adapter = __esm({
13084
13252
  }
13085
13253
  this.syncMessageViews();
13086
13254
  const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
13255
+ if (this.currentTurnScope) {
13256
+ LOG.info(
13257
+ "CLI",
13258
+ `[${this.cliType}] commitCurrentTranscript committedMessages=${this.committedMessages.length} finalLastAssistant=${JSON.stringify(summarizeCliTraceText(lastAssistant?.content || "", 220)).slice(0, 260)}`
13259
+ );
13260
+ }
13087
13261
  this.recordTrace("commit_transcript", {
13088
13262
  parsedStatus: parsed.status || null,
13089
13263
  messageCount: this.committedMessages.length,
@@ -13103,11 +13277,18 @@ var init_provider_cli_adapter = __esm({
13103
13277
  `[${this.cliType}] Commit without assistant turn: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
13104
13278
  );
13105
13279
  }
13280
+ const hasAssistant = !!lastAssistant;
13106
13281
  return {
13107
- hasAssistant: !!lastAssistant,
13282
+ hasAssistant,
13108
13283
  assistantContent: lastAssistant?.content || ""
13109
13284
  };
13110
13285
  }
13286
+ if (this.currentTurnScope) {
13287
+ LOG.info(
13288
+ "CLI",
13289
+ `[${this.cliType}] commitCurrentTranscript parsed.messages=none responseBufferLen=${this.responseBuffer.length} accumulatedBufferLen=${this.accumulatedBuffer.length} parsedStatus=${parsed?.status || "-"} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"}`
13290
+ );
13291
+ }
13111
13292
  return {
13112
13293
  hasAssistant: false,
13113
13294
  assistantContent: ""
@@ -13193,19 +13374,25 @@ var init_provider_cli_adapter = __esm({
13193
13374
  this.currentTurnScope,
13194
13375
  screenText
13195
13376
  );
13196
- const shouldPreferCommittedMessages = !this.currentTurnScope && this.currentStatus === "idle" && !this.activeModal;
13377
+ if (this.maybeCommitVisibleIdleTranscript(parsed)) {
13378
+ return this.getScriptParsedStatus();
13379
+ }
13380
+ const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
13197
13381
  let result;
13198
13382
  if (parsed && Array.isArray(parsed.messages)) {
13199
- const hydratedMessages = shouldPreferCommittedMessages ? this.committedMessages.map((message, index) => buildChatMessage({
13200
- ...message,
13201
- id: message.id || `msg_${index}`,
13202
- index: typeof message.index === "number" ? message.index : index,
13203
- receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
13204
- })) : hydrateCliParsedMessages(parsed.messages, {
13383
+ const parsedHydratedMessages = hydrateCliParsedMessages(parsed.messages, {
13205
13384
  committedMessages: this.committedMessages,
13206
13385
  scope: this.currentTurnScope,
13207
13386
  lastOutputAt: this.lastOutputAt
13208
13387
  });
13388
+ const committedHydratedMessages = this.committedMessages.map((message, index) => buildChatMessage({
13389
+ ...message,
13390
+ id: message.id || `msg_${index}`,
13391
+ index: typeof message.index === "number" ? message.index : index,
13392
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
13393
+ }));
13394
+ const shouldPreferCommittedHistoryReplay = !this.currentTurnScope && !this.activeModal && committedHydratedMessages.length > parsedHydratedMessages.length;
13395
+ const hydratedMessages = shouldPreferCommittedMessages || shouldPreferCommittedHistoryReplay ? committedHydratedMessages : parsedHydratedMessages;
13209
13396
  result = {
13210
13397
  id: parsed.id || "cli_session",
13211
13398
  status: parsed.status || this.currentStatus,
@@ -13229,6 +13416,23 @@ var init_provider_cli_adapter = __esm({
13229
13416
  activeModal: this.activeModal
13230
13417
  };
13231
13418
  }
13419
+ const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
13420
+ const shouldClampStaleGeneratingToIdle = result?.status === "generating" && this.currentStatus === "idle" && !this.currentTurnScope && !result?.activeModal && hasVisibleAssistantMessage;
13421
+ if (shouldClampStaleGeneratingToIdle) {
13422
+ result = {
13423
+ ...result,
13424
+ status: "idle",
13425
+ messages: Array.isArray(result.messages) ? result.messages.map((message) => {
13426
+ if (message?.role !== "assistant" || !message?.meta?.streaming) return message;
13427
+ const nextMeta = { ...message.meta || {} };
13428
+ delete nextMeta.streaming;
13429
+ return {
13430
+ ...message,
13431
+ ...Object.keys(nextMeta).length > 0 ? { meta: nextMeta } : { meta: void 0 }
13432
+ };
13433
+ }) : result.messages
13434
+ };
13435
+ }
13232
13436
  this.parsedStatusCache = {
13233
13437
  committedMessagesRef: this.committedMessages,
13234
13438
  responseBuffer: this.responseBuffer,
@@ -13361,9 +13565,27 @@ ${data.message || ""}`.trim();
13361
13565
  }
13362
13566
  }
13363
13567
  if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
13364
- if (this.isWaitingForResponse && !allowInputDuringGeneration) {
13568
+ const parsedStatusBeforeSend = !allowInputDuringGeneration ? (() => {
13569
+ try {
13570
+ return this.getScriptParsedStatus?.() || null;
13571
+ } catch {
13572
+ return null;
13573
+ }
13574
+ })() : null;
13575
+ const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
13576
+ const parsedMessagesBeforeSend = Array.isArray(parsedStatusBeforeSend?.messages) ? parsedStatusBeforeSend.messages.filter((message) => message && (message.role === "user" || message.role === "assistant")) : [];
13577
+ const shouldCommitParsedIdleBeforeSend = !allowInputDuringGeneration && parsedSessionStatus === "idle" && parsedMessagesBeforeSend.length > this.committedMessages.length && parsedMessagesBeforeSend.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
13578
+ if (shouldCommitParsedIdleBeforeSend) {
13579
+ this.commitCurrentTranscript();
13580
+ }
13581
+ if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
13365
13582
  throw new Error(`${this.cliName} is still processing the previous prompt`);
13366
13583
  }
13584
+ if (this.isWaitingForResponse && !allowInputDuringGeneration) {
13585
+ if (!this.clearStaleIdleResponseGuard("send_message_guard")) {
13586
+ throw new Error(`${this.cliName} is still processing the previous prompt`);
13587
+ }
13588
+ }
13367
13589
  const blockingModal = this.activeModal || this.getStartupConfirmationModal(this.terminalScreen.getText() || "");
13368
13590
  if (blockingModal || this.currentStatus === "waiting_approval") {
13369
13591
  throw new Error(`${this.cliName} is awaiting confirmation before it can accept a prompt`);
@@ -13443,7 +13665,7 @@ ${data.message || ""}`.trim();
13443
13665
  this.submitRetryTimer = null;
13444
13666
  if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
13445
13667
  if (this.currentStatus === "waiting_approval") return;
13446
- if ((this.responseBuffer || "").trim()) return;
13668
+ if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
13447
13669
  const screenText2 = this.terminalScreen.getText();
13448
13670
  if (!promptLikelyVisible(screenText2, normalizedPromptSnippet)) return;
13449
13671
  if (/Esc to interrupt|Do you want to proceed|This command requires approval|Allow Codex to|Approve and run now|Always approve this session|Running…|Running\.\.\./i.test(screenText2)) return;
@@ -13480,7 +13702,7 @@ ${data.message || ""}`.trim();
13480
13702
  this.submitRetryTimer = null;
13481
13703
  if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
13482
13704
  if (this.currentStatus === "waiting_approval") return;
13483
- if ((this.responseBuffer || "").trim()) return;
13705
+ if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
13484
13706
  const screenText = this.terminalScreen.getText();
13485
13707
  if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
13486
13708
  LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
@@ -13879,6 +14101,30 @@ ${data.message || ""}`.trim();
13879
14101
  });
13880
14102
 
13881
14103
  // ../../oss/packages/daemon-core/src/providers/cli-provider-instance.ts
14104
+ function normalizePersistableCliHistoryContent(content) {
14105
+ return flattenContent(content).replace(/\s+/g, " ").trim();
14106
+ }
14107
+ function buildPersistableCliHistorySignature(message) {
14108
+ return [
14109
+ String(message.role || ""),
14110
+ String(message.kind || ""),
14111
+ String(message.senderName || ""),
14112
+ normalizePersistableCliHistoryContent(message.content)
14113
+ ].join("|");
14114
+ }
14115
+ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages) {
14116
+ if (!Array.isArray(currentMessages) || currentMessages.length === 0) return [];
14117
+ if (!Array.isArray(previousMessages) || previousMessages.length === 0) return currentMessages;
14118
+ const previousSignatures = previousMessages.map(buildPersistableCliHistorySignature);
14119
+ const currentSignatures = currentMessages.map(buildPersistableCliHistorySignature);
14120
+ let sharedPrefixLength = 0;
14121
+ while (sharedPrefixLength < previousSignatures.length && sharedPrefixLength < currentSignatures.length && previousSignatures[sharedPrefixLength] === currentSignatures[sharedPrefixLength]) {
14122
+ sharedPrefixLength += 1;
14123
+ }
14124
+ if (sharedPrefixLength === currentSignatures.length) return [];
14125
+ if (sharedPrefixLength === previousSignatures.length) return currentMessages.slice(sharedPrefixLength);
14126
+ return currentMessages;
14127
+ }
13882
14128
  function getDatabaseSync() {
13883
14129
  if (CachedDatabaseSync) return CachedDatabaseSync;
13884
14130
  const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path12.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
@@ -13977,6 +14223,7 @@ var init_cli_provider_instance = __esm({
13977
14223
  appliedEffectKeys = /* @__PURE__ */ new Set();
13978
14224
  historyWriter;
13979
14225
  runtimeMessages = [];
14226
+ lastPersistedHistoryMessages = [];
13980
14227
  instanceId;
13981
14228
  suppressIdleHistoryReplay = false;
13982
14229
  errorMessage = void 0;
@@ -14017,6 +14264,13 @@ var init_cli_provider_instance = __esm({
14017
14264
  this.providerSessionId,
14018
14265
  this.instanceId
14019
14266
  );
14267
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
14268
+ role: message.role,
14269
+ content: message.content,
14270
+ kind: message.kind,
14271
+ senderName: message.senderName,
14272
+ receivedAt: message.receivedAt
14273
+ }));
14020
14274
  this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
14021
14275
  if (restoredHistory.messages.length > 0) {
14022
14276
  this.adapter.seedCommittedMessages(
@@ -14148,15 +14402,24 @@ var init_cli_provider_instance = __esm({
14148
14402
  messagesToSave = messagesToSave.slice(0, lastIdx);
14149
14403
  }
14150
14404
  }
14151
- if (!shouldSkipReplayPersist && messagesToSave.length > 0) {
14405
+ const normalizedMessagesToSave = messagesToSave.map((message) => ({
14406
+ role: message.role,
14407
+ content: flattenContent(message.content),
14408
+ kind: typeof message.kind === "string" ? message.kind : void 0,
14409
+ senderName: typeof message.senderName === "string" ? message.senderName : void 0,
14410
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
14411
+ }));
14412
+ if (!shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
14413
+ const incrementalMessages = buildIncrementalHistoryAppendMessages(this.lastPersistedHistoryMessages, normalizedMessagesToSave);
14152
14414
  this.historyWriter.appendNewMessages(
14153
14415
  this.type,
14154
- messagesToSave,
14416
+ incrementalMessages,
14155
14417
  parsedStatus?.title || dirName,
14156
14418
  this.instanceId,
14157
14419
  this.providerSessionId
14158
14420
  );
14159
14421
  }
14422
+ this.lastPersistedHistoryMessages = normalizedMessagesToSave;
14160
14423
  }
14161
14424
  this.applyProviderResponse(parsedStatus, { phase: "immediate" });
14162
14425
  const surface = resolveProviderStateSurface({
@@ -14172,7 +14435,7 @@ var init_cli_provider_instance = __esm({
14172
14435
  activeChat: {
14173
14436
  id: `${this.type}_${this.workingDir}`,
14174
14437
  title: parsedStatus?.title || dirName,
14175
- status: parseErrorMessage ? "error" : autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : parsedStatus?.status || visibleStatus,
14438
+ status: parseErrorMessage ? "error" : autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : adapterStatus.status !== "idle" ? visibleStatus : parsedStatus?.status || visibleStatus,
14176
14439
  messages: mergedMessages,
14177
14440
  activeModal: autoApproveActive ? null : parsedStatus?.activeModal ?? adapterStatus.activeModal,
14178
14441
  inputContent: ""
@@ -14404,6 +14667,7 @@ var init_cli_provider_instance = __esm({
14404
14667
  }
14405
14668
  if (data.sessionEvent === "new_session") {
14406
14669
  this.runtimeMessages = [];
14670
+ this.lastPersistedHistoryMessages = [];
14407
14671
  this.suppressIdleHistoryReplay = false;
14408
14672
  this.adapter.clearHistory();
14409
14673
  }
@@ -44865,6 +45129,13 @@ data: ${JSON.stringify(msg.data)}
44865
45129
  });
44866
45130
 
44867
45131
  // ../../oss/packages/daemon-core/src/cli-adapters/session-host-transport.ts
45132
+ function shouldResumeAttachedSession(record2) {
45133
+ if (!record2) return false;
45134
+ if (record2.lifecycle === "interrupted") return true;
45135
+ if (record2.lifecycle !== "stopped") return false;
45136
+ if (record2.meta?.restoredFromStorage === true) return true;
45137
+ return typeof record2.meta?.runtimeRecoveryState === "string" && String(record2.meta.runtimeRecoveryState).trim().length > 0;
45138
+ }
44868
45139
  var SessionHostRuntimeTransport, SessionHostPtyTransportFactory;
44869
45140
  var init_session_host_transport = __esm({
44870
45141
  "../../oss/packages/daemon-core/src/cli-adapters/session-host-transport.ts"() {
@@ -45044,7 +45315,7 @@ var init_session_host_transport = __esm({
45044
45315
  payload: {}
45045
45316
  });
45046
45317
  const existingRecord = existingRecords.success && existingRecords.result ? existingRecords.result.find((item) => item.sessionId === this.options.runtimeId) || null : null;
45047
- if (existingRecord?.lifecycle === "interrupted") {
45318
+ if (shouldResumeAttachedSession(existingRecord)) {
45048
45319
  const resumeResponse = await this.client.request({
45049
45320
  type: "resume_session",
45050
45321
  payload: {
@@ -45354,6 +45625,8 @@ var init_runtime_support = __esm({
45354
45625
  // ../../oss/packages/daemon-core/src/session-host/startup-restore-policy.js
45355
45626
  function shouldAutoRestoreHostedSessionsOnStartup(env3 = process.env) {
45356
45627
  const raw = typeof env3.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP === "string" ? env3.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP.trim().toLowerCase() : "";
45628
+ if (!raw) return true;
45629
+ if (raw === "0" || raw === "false" || raw === "no") return false;
45357
45630
  return raw === "1" || raw === "true" || raw === "yes";
45358
45631
  }
45359
45632
  var init_startup_restore_policy = __esm({
@@ -86108,7 +86381,7 @@ var init_adhdev_daemon = __esm({
86108
86381
  init_source();
86109
86382
  init_version();
86110
86383
  init_src();
86111
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.83" });
86384
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.85" });
86112
86385
  AdhdevDaemon = class _AdhdevDaemon {
86113
86386
  localHttpServer = null;
86114
86387
  localWss = null;