@adhdev/daemon-standalone 0.9.18 → 0.9.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -29827,6 +29827,7 @@ var require_dist2 = __commonJS({
29827
29827
  var provider_cli_adapter_exports = {};
29828
29828
  __export2(provider_cli_adapter_exports, {
29829
29829
  ProviderCliAdapter: () => ProviderCliAdapter,
29830
+ appendBoundedText: () => appendBoundedText,
29830
29831
  normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
29831
29832
  });
29832
29833
  function normalizeComparableTranscriptText(value) {
@@ -29859,6 +29860,14 @@ var require_dist2 = __commonJS({
29859
29860
  }
29860
29861
  return false;
29861
29862
  }
29863
+ function appendBoundedText(current, chunk, maxChars) {
29864
+ if (!chunk) return current.length <= maxChars ? current : current.slice(-maxChars);
29865
+ if (maxChars <= 0) return "";
29866
+ if (chunk.length >= maxChars) return chunk.slice(-maxChars);
29867
+ const keepFromCurrent = maxChars - chunk.length;
29868
+ if (current.length <= keepFromCurrent) return current + chunk;
29869
+ return current.slice(-keepFromCurrent) + chunk;
29870
+ }
29862
29871
  var os10;
29863
29872
  var ProviderCliAdapter;
29864
29873
  var init_provider_cli_adapter = __esm2({
@@ -29937,15 +29946,17 @@ var require_dist2 = __commonJS({
29937
29946
  startupFirstOutputAt = 0;
29938
29947
  // PTY I/O
29939
29948
  onPtyDataCallback = null;
29940
- pendingOutputParseBuffer = "";
29949
+ pendingOutputParseChunks = [];
29941
29950
  pendingOutputParseTimer = null;
29942
- ptyOutputBuffer = "";
29951
+ ptyOutputChunks = [];
29943
29952
  ptyOutputFlushTimer = null;
29944
29953
  pendingTerminalQueryTail = "";
29945
29954
  lastOutputAt = 0;
29946
29955
  lastNonEmptyOutputAt = 0;
29947
29956
  lastScreenChangeAt = 0;
29948
29957
  lastScreenSnapshot = "";
29958
+ lastScreenText = "";
29959
+ lastScreenSnapshotReadAt = Number.NEGATIVE_INFINITY;
29949
29960
  // Server log forwarding
29950
29961
  serverConn = null;
29951
29962
  logBuffer = [];
@@ -29991,6 +30002,9 @@ var require_dist2 = __commonJS({
29991
30002
  traceSeq = 0;
29992
30003
  traceSessionId = "";
29993
30004
  parsedStatusCache = null;
30005
+ lastStatusHotPathParseAt = Number.NEGATIVE_INFINITY;
30006
+ static STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS = 1e3;
30007
+ static SCREEN_SNAPSHOT_MIN_INTERVAL_MS = 250;
29994
30008
  static MAX_TRACE_ENTRIES = 250;
29995
30009
  providerResolutionMeta;
29996
30010
  static FINISH_RETRY_DELAY_MS = 300;
@@ -29999,6 +30013,30 @@ var require_dist2 = __commonJS({
29999
30013
  this.messages = [...this.committedMessages];
30000
30014
  this.structuredMessages = [...this.committedMessages];
30001
30015
  }
30016
+ readTerminalScreenText(now = Date.now()) {
30017
+ const screenText = this.terminalScreen.getText() || "";
30018
+ this.lastScreenText = screenText;
30019
+ this.lastScreenSnapshotReadAt = now;
30020
+ return screenText;
30021
+ }
30022
+ shouldReadTerminalScreenSnapshot(now) {
30023
+ if (!this.lastScreenText) return true;
30024
+ return now - this.lastScreenSnapshotReadAt >= _ProviderCliAdapter.SCREEN_SNAPSHOT_MIN_INTERVAL_MS;
30025
+ }
30026
+ resetTerminalScreen(rows, cols) {
30027
+ this.terminalScreen.reset(rows, cols);
30028
+ this.lastScreenText = "";
30029
+ this.lastScreenSnapshot = "";
30030
+ this.lastScreenChangeAt = 0;
30031
+ this.lastScreenSnapshotReadAt = Number.NEGATIVE_INFINITY;
30032
+ }
30033
+ getFreshParsedStatusCache() {
30034
+ const cached2 = this.parsedStatusCache;
30035
+ if (cached2 && cached2.committedMessagesRef === this.committedMessages && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.accumulatedRawBuffer === this.accumulatedRawBuffer && cached2.screenText === this.lastScreenText && cached2.currentStatus === this.currentStatus && cached2.activeModal === this.activeModal && cached2.cliName === this.cliName && cached2.lastOutputAt === this.lastOutputAt) {
30036
+ return cached2.result;
30037
+ }
30038
+ return null;
30039
+ }
30002
30040
  getIdleFinishConfirmMs() {
30003
30041
  return this.timeouts.idleFinishConfirm;
30004
30042
  }
@@ -30113,9 +30151,9 @@ var require_dist2 = __commonJS({
30113
30151
  clearTimeout(this.pendingOutputParseTimer);
30114
30152
  this.pendingOutputParseTimer = null;
30115
30153
  }
30116
- if (!this.pendingOutputParseBuffer) return;
30117
- const rawData = this.pendingOutputParseBuffer;
30118
- this.pendingOutputParseBuffer = "";
30154
+ if (this.pendingOutputParseChunks.length === 0) return;
30155
+ const rawData = this.pendingOutputParseChunks.join("");
30156
+ this.pendingOutputParseChunks = [];
30119
30157
  this.handleOutput(rawData);
30120
30158
  }
30121
30159
  async spawn() {
@@ -30170,7 +30208,7 @@ var require_dist2 = __commonJS({
30170
30208
  terminalScreen: this.terminalScreen
30171
30209
  });
30172
30210
  }
30173
- this.pendingOutputParseBuffer += data;
30211
+ this.pendingOutputParseChunks.push(data);
30174
30212
  if (!this.pendingOutputParseTimer) {
30175
30213
  this.pendingOutputParseTimer = setTimeout(() => {
30176
30214
  this.pendingOutputParseTimer = null;
@@ -30178,13 +30216,13 @@ var require_dist2 = __commonJS({
30178
30216
  }, this.timeouts.ptyFlush);
30179
30217
  }
30180
30218
  if (this.onPtyDataCallback) {
30181
- this.ptyOutputBuffer += data;
30219
+ this.ptyOutputChunks.push(data);
30182
30220
  if (!this.ptyOutputFlushTimer) {
30183
30221
  this.ptyOutputFlushTimer = setTimeout(() => {
30184
- if (this.ptyOutputBuffer && this.onPtyDataCallback) {
30185
- this.onPtyDataCallback(this.ptyOutputBuffer);
30222
+ if (this.ptyOutputChunks.length > 0 && this.onPtyDataCallback) {
30223
+ this.onPtyDataCallback(this.ptyOutputChunks.join(""));
30186
30224
  }
30187
- this.ptyOutputBuffer = "";
30225
+ this.ptyOutputChunks = [];
30188
30226
  this.ptyOutputFlushTimer = null;
30189
30227
  }, this.timeouts.ptyFlush);
30190
30228
  }
@@ -30209,7 +30247,7 @@ var require_dist2 = __commonJS({
30209
30247
  clearTimeout(this.startupSettleTimer);
30210
30248
  this.startupSettleTimer = null;
30211
30249
  }
30212
- this.terminalScreen.reset(24, 80);
30250
+ this.resetTerminalScreen(24, 80);
30213
30251
  this.pendingTerminalQueryTail = "";
30214
30252
  this.currentTurnScope = null;
30215
30253
  this.finishRetryCount = 0;
@@ -30231,11 +30269,12 @@ var require_dist2 = __commonJS({
30231
30269
  this.terminalScreen.write(rawData);
30232
30270
  const cleanData = sanitizeTerminalText(rawData);
30233
30271
  const now = Date.now();
30234
- const screenText = this.terminalScreen.getText();
30235
- const normalizedScreenSnapshot = normalizeScreenSnapshot(screenText);
30272
+ const shouldReadScreen = this.shouldReadTerminalScreenSnapshot(now);
30273
+ const screenText = shouldReadScreen ? this.readTerminalScreenText(now) : this.lastScreenText;
30274
+ const normalizedScreenSnapshot = shouldReadScreen ? normalizeScreenSnapshot(screenText) : this.lastScreenSnapshot;
30236
30275
  this.lastOutputAt = now;
30237
30276
  if (cleanData.trim()) this.lastNonEmptyOutputAt = now;
30238
- if (normalizedScreenSnapshot !== this.lastScreenSnapshot) {
30277
+ if (shouldReadScreen && normalizedScreenSnapshot !== this.lastScreenSnapshot) {
30239
30278
  this.lastScreenSnapshot = normalizedScreenSnapshot;
30240
30279
  this.lastScreenChangeAt = now;
30241
30280
  }
@@ -30257,7 +30296,7 @@ var require_dist2 = __commonJS({
30257
30296
  this.scheduleStartupSettleCheck();
30258
30297
  }
30259
30298
  if (this.isWaitingForResponse && cleanData) {
30260
- this.responseBuffer = (this.responseBuffer + cleanData).slice(-8e3);
30299
+ this.responseBuffer = appendBoundedText(this.responseBuffer, cleanData, 8e3);
30261
30300
  }
30262
30301
  if (cleanData.trim()) {
30263
30302
  if (this.serverConn) {
@@ -30266,11 +30305,11 @@ var require_dist2 = __commonJS({
30266
30305
  this.logBuffer.push({ message: cleanData.trim(), level: "info" });
30267
30306
  }
30268
30307
  }
30269
- this.recentOutputBuffer = (this.recentOutputBuffer + cleanData).slice(-1e3);
30270
30308
  const prevAccumulatedLen = this.accumulatedBuffer.length;
30271
30309
  const prevAccumulatedRawLen = this.accumulatedRawBuffer.length;
30272
- this.accumulatedBuffer = (this.accumulatedBuffer + cleanData).slice(-_ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
30273
- this.accumulatedRawBuffer = (this.accumulatedRawBuffer + rawData).slice(-_ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
30310
+ this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, 1e3);
30311
+ this.accumulatedBuffer = appendBoundedText(this.accumulatedBuffer, cleanData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
30312
+ this.accumulatedRawBuffer = appendBoundedText(this.accumulatedRawBuffer, rawData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
30274
30313
  if (this.currentTurnScope) {
30275
30314
  const droppedClean = prevAccumulatedLen + cleanData.length - this.accumulatedBuffer.length;
30276
30315
  const droppedRaw = prevAccumulatedRawLen + rawData.length - this.accumulatedRawBuffer.length;
@@ -30281,14 +30320,14 @@ var require_dist2 = __commonJS({
30281
30320
  this.currentTurnScope.rawBufferStart = Math.max(0, this.currentTurnScope.rawBufferStart - droppedRaw);
30282
30321
  }
30283
30322
  }
30284
- this.resolveStartupState("output");
30323
+ this.resolveStartupState("output", screenText, normalizedScreenSnapshot, now);
30285
30324
  this.scheduleSettle();
30286
30325
  }
30287
- resolveStartupState(trigger) {
30326
+ resolveStartupState(trigger, screenTextOverride, normalizedScreenOverride, nowOverride) {
30288
30327
  if (!this.startupParseGate) return;
30289
- const now = Date.now();
30290
- const screenText = this.terminalScreen.getText() || "";
30291
- const normalizedScreen = normalizeScreenSnapshot(screenText);
30328
+ const now = typeof nowOverride === "number" ? nowOverride : Date.now();
30329
+ const screenText = typeof screenTextOverride === "string" ? screenTextOverride : this.readTerminalScreenText();
30330
+ const normalizedScreen = typeof normalizedScreenOverride === "string" ? normalizedScreenOverride : normalizeScreenSnapshot(screenText);
30292
30331
  const hasStartupOutput = !!this.startupFirstOutputAt || !!normalizedScreen.trim();
30293
30332
  if (!hasStartupOutput) return;
30294
30333
  const stableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
@@ -30523,40 +30562,28 @@ var require_dist2 = __commonJS({
30523
30562
  }, delayTime);
30524
30563
  return;
30525
30564
  }
30526
- const tail = this.settledBuffer;
30527
- const screenText = this.terminalScreen.getText() || "";
30528
30565
  this.resolveStartupState("settled");
30529
- if (this.startupParseGate) {
30530
- return;
30531
- }
30532
- const parsedTranscript = this.parseCurrentTranscript(
30533
- this.committedMessages,
30534
- this.responseBuffer,
30535
- this.currentTurnScope
30536
- );
30537
- const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsedTranscript.activeModal : null;
30538
- const modal = this.runParseApproval(tail) || parsedModal;
30539
- const rawScriptStatus = this.runDetectStatus(tail);
30540
- const scriptStatus = parsedTranscript?.status === "waiting_approval" && modal ? "waiting_approval" : rawScriptStatus;
30541
- const parsedMessages = Array.isArray(parsedTranscript?.messages) ? normalizeCliParsedMessages(parsedTranscript.messages, {
30566
+ if (this.startupParseGate) return;
30567
+ const session = this.runParseSession();
30568
+ if (!session) return;
30569
+ const { status, messages, modal, parsedStatus } = session;
30570
+ const parsedMessages = normalizeCliParsedMessages(messages, {
30542
30571
  committedMessages: this.committedMessages,
30543
30572
  scope: this.currentTurnScope,
30544
30573
  lastOutputAt: this.lastOutputAt
30545
- }) : [];
30546
- if (this.maybeCommitVisibleIdleTranscript(parsedTranscript)) {
30547
- return;
30548
- }
30549
- const lastParsedAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
30550
- const parsedShowsLiveAssistantProgress = parsedTranscript?.status === "generating" && !!lastParsedAssistant && parsedMessages.length > this.committedMessages.length;
30574
+ });
30575
+ if (this.maybeCommitVisibleIdleTranscript(session, parsedMessages)) return;
30576
+ const lastParsedAssistant = [...parsedMessages].reverse().find((m) => m.role === "assistant");
30551
30577
  const normalizedPromptSnippet = normalizePromptText(this.submitRetryPromptSnippet || this.currentTurnScope?.prompt || "");
30578
+ const screenText = this.terminalScreen.getText() || "";
30552
30579
  this.recordTrace("settled", {
30553
- tail: summarizeCliTraceText(tail, 500),
30580
+ tail: summarizeCliTraceText(this.settledBuffer, 500),
30554
30581
  screenText: summarizeCliTraceText(screenText, 1200),
30555
- detectStatus: scriptStatus,
30556
- parsedStatus: parsedTranscript?.status || null,
30582
+ detectStatus: status,
30583
+ parsedStatus: parsedStatus || null,
30557
30584
  parsedMessageCount: parsedMessages.length,
30558
30585
  parsedLastAssistant: lastParsedAssistant ? summarizeCliTraceText(lastParsedAssistant.content, 280) : "",
30559
- parsedActiveModal: parsedTranscript?.activeModal ?? null,
30586
+ parsedActiveModal: modal,
30560
30587
  approval: modal,
30561
30588
  ...buildCliTraceParseSnapshot({
30562
30589
  accumulatedBuffer: this.accumulatedBuffer,
@@ -30590,36 +30617,36 @@ var require_dist2 = __commonJS({
30590
30617
  `[${this.cliType}] Settled without assistant: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 220)).slice(0, 260)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"}`
30591
30618
  );
30592
30619
  }
30593
- if (!scriptStatus) return;
30620
+ if (!status) return;
30594
30621
  const prevStatus = this.currentStatus;
30595
- const ctx = { now, screenText, modal, scriptStatus, parsedTranscript, parsedMessages, lastParsedAssistant, parsedShowsLiveAssistantProgress, prevStatus };
30622
+ const ctx = { now, modal, status, parsedMessages, lastParsedAssistant, parsedStatus: parsedStatus || null, prevStatus };
30596
30623
  if (!this.applyPendingScriptStatusDebounce(ctx)) return;
30597
30624
  const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
30598
30625
  LOG2.info(
30599
30626
  "CLI",
30600
- `[${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)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 160)).slice(0, 220)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 160)).slice(0, 220)}`
30627
+ `[${this.cliType}] settled diagnostics prompt=${JSON.stringify(this.currentTurnScope?.prompt || "").slice(0, 140)} status=${String(status || "")} parsedStatus=${String(parsedStatus || "")} parsedMsgCount=${parsedMessages.length} lastParsedAssistant=${JSON.stringify(summarizeCliTraceText(lastParsedAssistant?.content || "", 120)).slice(0, 160)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 160)).slice(0, 220)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 160)).slice(0, 220)}`
30601
30628
  );
30602
- const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(parsedTranscript?.status === "idle" && !!lastParsedAssistant);
30629
+ const shouldHoldGenerating = status === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(parsedStatus === "idle" && !!lastParsedAssistant);
30603
30630
  if (shouldHoldGenerating) {
30604
30631
  this.applyHoldGenerating(ctx, recentInteractiveActivity);
30605
30632
  return;
30606
30633
  }
30607
- if (scriptStatus === "waiting_approval") {
30634
+ if (status === "waiting_approval") {
30608
30635
  this.applyWaitingApproval(ctx);
30609
30636
  return;
30610
30637
  }
30611
- if (scriptStatus === "generating") {
30638
+ if (status === "generating") {
30612
30639
  this.applyGenerating(ctx);
30613
30640
  return;
30614
30641
  }
30615
- if (scriptStatus === "idle") {
30642
+ if (status === "idle") {
30616
30643
  this.applyIdle(ctx, now);
30617
30644
  }
30618
30645
  }
30619
30646
  // Returns false if the caller should bail out (debounce pending).
30620
30647
  applyPendingScriptStatusDebounce(ctx) {
30621
- const { now, scriptStatus, prevStatus } = ctx;
30622
- const shouldDebounce = prevStatus === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && (scriptStatus === "generating" || scriptStatus === "waiting_approval");
30648
+ const { now, status, prevStatus } = ctx;
30649
+ const shouldDebounce = prevStatus === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && (status === "generating" || status === "waiting_approval");
30623
30650
  if (!shouldDebounce) {
30624
30651
  this.pendingScriptStatus = null;
30625
30652
  this.pendingScriptStatusSince = 0;
@@ -30637,8 +30664,8 @@ var require_dist2 = __commonJS({
30637
30664
  this.evaluateSettled();
30638
30665
  }, delayMs);
30639
30666
  };
30640
- if (this.pendingScriptStatus !== scriptStatus) {
30641
- this.pendingScriptStatus = scriptStatus;
30667
+ if (this.pendingScriptStatus !== status) {
30668
+ this.pendingScriptStatus = status;
30642
30669
  this.pendingScriptStatusSince = now;
30643
30670
  armPending(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS);
30644
30671
  return false;
@@ -30651,7 +30678,7 @@ var require_dist2 = __commonJS({
30651
30678
  return true;
30652
30679
  }
30653
30680
  applyHoldGenerating(ctx, recentInteractiveActivity) {
30654
- const { scriptStatus } = ctx;
30681
+ const { status } = ctx;
30655
30682
  this.clearIdleFinishCandidate("hold_generating_recent_activity");
30656
30683
  this.setStatus("generating", "recent_activity_hold");
30657
30684
  if (this.idleTimeout) clearTimeout(this.idleTimeout);
@@ -30662,7 +30689,7 @@ var require_dist2 = __commonJS({
30662
30689
  }
30663
30690
  }, this.timeouts.generatingIdle);
30664
30691
  this.recordTrace("hold_generating_recent_activity", {
30665
- scriptStatus,
30692
+ scriptStatus: status,
30666
30693
  recentInteractiveActivity,
30667
30694
  lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
30668
30695
  lastScreenChangeAt: this.lastScreenChangeAt,
@@ -30716,11 +30743,13 @@ var require_dist2 = __commonJS({
30716
30743
  }
30717
30744
  }
30718
30745
  applyGenerating(ctx) {
30719
- const { screenText, modal, parsedShowsLiveAssistantProgress, prevStatus } = ctx;
30746
+ const { modal, parsedMessages, lastParsedAssistant, parsedStatus, prevStatus } = ctx;
30720
30747
  this.clearIdleFinishCandidate("generating");
30748
+ const screenText = this.terminalScreen.getText() || "";
30721
30749
  const effectiveScreenText = screenText || this.accumulatedBuffer;
30722
30750
  const noActiveTurn = !this.currentTurnScope;
30723
30751
  const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(effectiveScreenText) || /accept edits on/i.test(effectiveScreenText) && (/Update available!/i.test(screenText) || /\/effort/i.test(screenText) || /^.*➜\s+\S+/m.test(effectiveScreenText));
30752
+ const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant && parsedMessages.length > this.committedMessages.length;
30724
30753
  if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
30725
30754
  return;
30726
30755
  }
@@ -30747,7 +30776,7 @@ var require_dist2 = __commonJS({
30747
30776
  this.onStatusChange?.();
30748
30777
  }
30749
30778
  applyIdle(ctx, now) {
30750
- const { screenText, modal, lastParsedAssistant, prevStatus } = ctx;
30779
+ const { modal, lastParsedAssistant, prevStatus } = ctx;
30751
30780
  if (prevStatus === "waiting_approval") {
30752
30781
  if (this.approvalExitTimeout) {
30753
30782
  clearTimeout(this.approvalExitTimeout);
@@ -30869,20 +30898,15 @@ var require_dist2 = __commonJS({
30869
30898
  this.setStatus("idle", "response_finished");
30870
30899
  this.onStatusChange?.();
30871
30900
  }
30872
- maybeCommitVisibleIdleTranscript(parsed) {
30901
+ maybeCommitVisibleIdleTranscript(session, parsedMessages) {
30873
30902
  const allowImmediateScriptIdleCommit = this.provider.allowInputDuringGeneration === true;
30874
30903
  if (!allowImmediateScriptIdleCommit) return false;
30875
- if (!parsed || !Array.isArray(parsed.messages) || parsed.status !== "idle" || !this.isWaitingForResponse || !this.currentTurnScope || this.activeModal || parsed.activeModal) {
30904
+ if (!session || session.status !== "idle" || !this.isWaitingForResponse || !this.currentTurnScope || this.activeModal || session.modal) {
30876
30905
  return false;
30877
30906
  }
30878
- const hydratedForIdleCommit = normalizeCliParsedMessages(parsed.messages, {
30879
- committedMessages: this.committedMessages,
30880
- scope: this.currentTurnScope,
30881
- lastOutputAt: this.lastOutputAt
30882
- });
30883
- const visibleAssistant = [...hydratedForIdleCommit].reverse().find((message) => message.role === "assistant" && message.content.trim());
30907
+ const visibleAssistant = [...parsedMessages].reverse().find((m) => m.role === "assistant" && m.content.trim());
30884
30908
  if (!visibleAssistant) return false;
30885
- this.committedMessages = hydratedForIdleCommit;
30909
+ this.committedMessages = parsedMessages;
30886
30910
  this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
30887
30911
  this.clearAllTimers();
30888
30912
  this.syncMessageViews();
@@ -30960,6 +30984,59 @@ var require_dist2 = __commonJS({
30960
30984
  };
30961
30985
  }
30962
30986
  // ─── Script Execution ──────────────────────────
30987
+ runParseSession() {
30988
+ if (typeof this.cliScripts?.parseSession === "function") {
30989
+ try {
30990
+ const screenText = this.terminalScreen.getText();
30991
+ const tail = this.recentOutputBuffer.slice(-500);
30992
+ const input = buildCliParseInput({
30993
+ accumulatedBuffer: this.accumulatedBuffer,
30994
+ accumulatedRawBuffer: this.accumulatedRawBuffer,
30995
+ recentOutputBuffer: this.recentOutputBuffer,
30996
+ terminalScreenText: screenText,
30997
+ baseMessages: this.committedMessages,
30998
+ partialResponse: this.responseBuffer,
30999
+ isWaitingForResponse: this.isWaitingForResponse,
31000
+ scope: this.currentTurnScope,
31001
+ runtimeSettings: this.runtimeSettings
31002
+ });
31003
+ const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
31004
+ this.parseErrorMessage = null;
31005
+ return session && typeof session === "object" ? session : null;
31006
+ } catch (e) {
31007
+ const message = e?.message || String(e);
31008
+ this.parseErrorMessage = message;
31009
+ LOG2.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
31010
+ return null;
31011
+ }
31012
+ }
31013
+ if (!this.cliScripts?.detectStatus && !this.cliScripts?.parseOutput) return null;
31014
+ try {
31015
+ const tail = this.settledBuffer;
31016
+ const parsedTranscript = this.parseCurrentTranscript(
31017
+ this.committedMessages,
31018
+ this.responseBuffer,
31019
+ this.currentTurnScope
31020
+ );
31021
+ const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((b2) => typeof b2 === "string" && b2.trim()) ? parsedTranscript.activeModal : null;
31022
+ const approval = this.runParseApproval(tail);
31023
+ const modal = approval || parsedModal;
31024
+ const rawStatus = this.runDetectStatus(tail);
31025
+ const parsedStatus = typeof parsedTranscript?.status === "string" ? parsedTranscript.status : null;
31026
+ const effectiveStatus = parsedStatus === "waiting_approval" && modal ? "waiting_approval" : rawStatus || parsedStatus || "idle";
31027
+ return {
31028
+ status: effectiveStatus,
31029
+ messages: Array.isArray(parsedTranscript?.messages) ? parsedTranscript.messages : [],
31030
+ modal,
31031
+ parsedStatus
31032
+ };
31033
+ } catch (e) {
31034
+ const message = e?.message || String(e);
31035
+ this.parseErrorMessage = message;
31036
+ LOG2.warn("CLI", `[${this.cliType}] parseSession fallback error: ${message}`);
31037
+ return null;
31038
+ }
31039
+ }
30963
31040
  runDetectStatus(text) {
30964
31041
  if (!this.cliScripts?.detectStatus) return null;
30965
31042
  try {
@@ -31033,14 +31110,21 @@ var require_dist2 = __commonJS({
31033
31110
  let effectiveStatus = this.projectEffectiveStatus(startupModal);
31034
31111
  let effectiveModal = startupModal || this.activeModal;
31035
31112
  if (!startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
31036
- try {
31037
- const parsed = this.getScriptParsedStatus();
31038
- const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
31039
- if (parsed?.status === "waiting_approval" && parsedModal) {
31040
- effectiveStatus = "waiting_approval";
31041
- effectiveModal = parsedModal;
31113
+ let parsed = this.getFreshParsedStatusCache();
31114
+ if (!parsed && effectiveStatus !== "idle") {
31115
+ const now = Date.now();
31116
+ if (now - this.lastStatusHotPathParseAt >= _ProviderCliAdapter.STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS) {
31117
+ this.lastStatusHotPathParseAt = now;
31118
+ try {
31119
+ parsed = this.getScriptParsedStatus();
31120
+ } catch {
31121
+ }
31042
31122
  }
31043
- } catch {
31123
+ }
31124
+ const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
31125
+ if (parsed?.status === "waiting_approval" && parsedModal) {
31126
+ effectiveStatus = "waiting_approval";
31127
+ effectiveModal = parsedModal;
31044
31128
  }
31045
31129
  }
31046
31130
  return {
@@ -31072,7 +31156,7 @@ var require_dist2 = __commonJS({
31072
31156
  * Called by command handler / dashboard for rich content rendering.
31073
31157
  */
31074
31158
  getScriptParsedStatus() {
31075
- const screenText = this.terminalScreen.getText();
31159
+ const screenText = this.readTerminalScreenText();
31076
31160
  const cached2 = this.parsedStatusCache;
31077
31161
  if (cached2 && cached2.committedMessagesRef === this.committedMessages && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.accumulatedRawBuffer === this.accumulatedRawBuffer && cached2.screenText === screenText && cached2.currentStatus === this.currentStatus && cached2.activeModal === this.activeModal && cached2.cliName === this.cliName && cached2.lastOutputAt === this.lastOutputAt) {
31078
31162
  return cached2.result;
@@ -31092,8 +31176,21 @@ var require_dist2 = __commonJS({
31092
31176
  this.onStatusChange?.();
31093
31177
  }
31094
31178
  }
31095
- if (this.maybeCommitVisibleIdleTranscript(parsed)) {
31096
- return this.getScriptParsedStatus();
31179
+ if (parsed && Array.isArray(parsed.messages)) {
31180
+ const hydratedForCommit = normalizeCliParsedMessages(parsed.messages, {
31181
+ committedMessages: this.committedMessages,
31182
+ scope: this.currentTurnScope,
31183
+ lastOutputAt: this.lastOutputAt
31184
+ });
31185
+ const fakeSession = {
31186
+ status: parsed.status || "idle",
31187
+ messages: parsed.messages,
31188
+ modal: parsedModal,
31189
+ parsedStatus: parsed.status || null
31190
+ };
31191
+ if (this.maybeCommitVisibleIdleTranscript(fakeSession, hydratedForCommit)) {
31192
+ return this.getScriptParsedStatus();
31193
+ }
31097
31194
  }
31098
31195
  const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
31099
31196
  let result;
@@ -31275,6 +31372,17 @@ var require_dist2 = __commonJS({
31275
31372
  }
31276
31373
  await this.sendMessage(promptText);
31277
31374
  }
31375
+ isSubmitStuck(normalizedPromptSnippet) {
31376
+ if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return false;
31377
+ if (this.hasActionableApproval()) return false;
31378
+ if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return false;
31379
+ const screenText = this.terminalScreen.getText();
31380
+ if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return false;
31381
+ const liveApproval = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
31382
+ if (liveApproval) return false;
31383
+ const liveStatus = this.runDetectStatus(screenText) || this.runDetectStatus(this.recentOutputBuffer);
31384
+ return liveStatus !== "generating" && liveStatus !== "waiting_approval";
31385
+ }
31278
31386
  async writeToPty(data) {
31279
31387
  if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
31280
31388
  await this.ptyProcess.write(data);
@@ -31298,6 +31406,121 @@ var require_dist2 = __commonJS({
31298
31406
  this.finishRetryTimer = null;
31299
31407
  }
31300
31408
  }
31409
+ commitSendUserTurn(state) {
31410
+ if (state.didCommitUserTurn) return;
31411
+ state.didCommitUserTurn = true;
31412
+ this.committedMessages.push({ role: "user", content: state.text, timestamp: Date.now() });
31413
+ this.syncMessageViews();
31414
+ }
31415
+ armResponseTimeout() {
31416
+ if (this.responseTimeout) clearTimeout(this.responseTimeout);
31417
+ this.responseTimeout = setTimeout(() => {
31418
+ if (this.isWaitingForResponse) this.finishResponse();
31419
+ }, this.timeouts.maxResponse);
31420
+ }
31421
+ writeSubmitKeyForRetry(mode) {
31422
+ void this.writeToPty(this.sendKey).catch((error48) => {
31423
+ LOG2.warn("CLI", `[${this.cliType}] ${mode} write failed: ${error48?.message || error48}`);
31424
+ });
31425
+ }
31426
+ retrySubmitIfStuck(state, attempt) {
31427
+ this.submitRetryTimer = null;
31428
+ if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
31429
+ const screenText = this.terminalScreen.getText();
31430
+ this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
31431
+ LOG2.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
31432
+ this.recordTrace("submit_write", {
31433
+ mode: "submit_retry",
31434
+ attempt,
31435
+ sendKey: this.sendKey,
31436
+ screenText: summarizeCliTraceText(screenText, 500)
31437
+ });
31438
+ this.writeSubmitKeyForRetry("submit_retry");
31439
+ if (attempt >= 3) {
31440
+ this.submitRetryUsed = true;
31441
+ return;
31442
+ }
31443
+ this.submitRetryTimer = setTimeout(() => this.retrySubmitIfStuck(state, attempt + 1), state.retryDelayMs);
31444
+ }
31445
+ retryImmediateSubmitIfStuck(state) {
31446
+ this.submitRetryTimer = null;
31447
+ if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
31448
+ const screenText = this.terminalScreen.getText();
31449
+ this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
31450
+ LOG2.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
31451
+ this.recordTrace("submit_write", {
31452
+ mode: "immediate_retry",
31453
+ attempt: 1,
31454
+ sendKey: this.sendKey,
31455
+ screenText: summarizeCliTraceText(screenText, 500)
31456
+ });
31457
+ this.writeSubmitKeyForRetry("immediate_retry");
31458
+ this.submitRetryUsed = true;
31459
+ }
31460
+ submitSendKey(state, completion) {
31461
+ if (!this.ptyProcess) {
31462
+ completion.resolveOnce();
31463
+ return;
31464
+ }
31465
+ this.submitPendingUntil = 0;
31466
+ const screenText = this.terminalScreen.getText();
31467
+ this.recordTrace("submit_write", {
31468
+ mode: "submit_key",
31469
+ sendKey: this.sendKey,
31470
+ screenText: summarizeCliTraceText(screenText, 500)
31471
+ });
31472
+ void this.writeToPty(this.sendKey).then(() => {
31473
+ this.commitSendUserTurn(state);
31474
+ this.submitRetryTimer = setTimeout(() => this.retrySubmitIfStuck(state, 1), state.retryDelayMs);
31475
+ this.armResponseTimeout();
31476
+ completion.resolveOnce();
31477
+ }, completion.rejectOnce);
31478
+ }
31479
+ submitImmediatePrompt(state, completion) {
31480
+ this.submitPendingUntil = 0;
31481
+ this.recordTrace("submit_write", {
31482
+ mode: "immediate",
31483
+ text: summarizeCliTraceText(state.text, 500),
31484
+ sendKey: this.sendKey,
31485
+ screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
31486
+ });
31487
+ void this.writeToPty(state.text + this.sendKey).then(() => {
31488
+ this.commitSendUserTurn(state);
31489
+ this.submitRetryTimer = setTimeout(() => this.retryImmediateSubmitIfStuck(state), state.retryDelayMs);
31490
+ this.armResponseTimeout();
31491
+ completion.resolveOnce();
31492
+ }, completion.rejectOnce);
31493
+ }
31494
+ waitForEchoAndSubmit(state, completion, submitStartedAt, lastNormalizedScreen = "", lastScreenChangeAt = submitStartedAt) {
31495
+ if (!this.ptyProcess) {
31496
+ completion.resolveOnce();
31497
+ return;
31498
+ }
31499
+ const now = Date.now();
31500
+ const elapsed = now - submitStartedAt;
31501
+ const screenText = this.terminalScreen.getText();
31502
+ const normalizedScreen = normalizePromptText(screenText);
31503
+ const nextScreenChangeAt = normalizedScreen !== lastNormalizedScreen ? now : lastScreenChangeAt;
31504
+ const echoVisible = !state.normalizedPromptSnippet || promptLikelyVisible(screenText, state.normalizedPromptSnippet);
31505
+ if (echoVisible) {
31506
+ const screenSettled = now - nextScreenChangeAt >= 500;
31507
+ if (elapsed >= state.submitDelayMs && screenSettled) {
31508
+ this.submitSendKey(state, completion);
31509
+ return;
31510
+ }
31511
+ }
31512
+ if (elapsed >= state.maxEchoWaitMs) {
31513
+ this.submitSendKey(state, completion);
31514
+ return;
31515
+ }
31516
+ setTimeout(() => this.waitForEchoAndSubmit(
31517
+ state,
31518
+ completion,
31519
+ submitStartedAt,
31520
+ normalizedScreen,
31521
+ nextScreenChangeAt
31522
+ ), 50);
31523
+ }
31301
31524
  async sendMessage(text) {
31302
31525
  if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
31303
31526
  const allowInputDuringGeneration = this.provider.allowInputDuringGeneration === true;
@@ -31373,12 +31596,13 @@ var require_dist2 = __commonJS({
31373
31596
  const submitDelayMs = this.sendDelayMs + Math.min(2e3, Math.max(0, estimatedLines - 1) * 350);
31374
31597
  const maxEchoWaitMs = submitDelayMs + Math.max(1500, Math.min(5e3, estimatedLines * 500));
31375
31598
  const retryDelayMs = Math.max(350, Math.min(1500, Math.max(this.sendDelayMs, submitDelayMs)));
31376
- let didCommitUserTurn = false;
31377
- const commitUserTurn = () => {
31378
- if (didCommitUserTurn) return;
31379
- didCommitUserTurn = true;
31380
- this.committedMessages.push({ role: "user", content: text, timestamp: Date.now() });
31381
- this.syncMessageViews();
31599
+ const sendState = {
31600
+ text,
31601
+ normalizedPromptSnippet,
31602
+ submitDelayMs,
31603
+ maxEchoWaitMs,
31604
+ retryDelayMs,
31605
+ didCommitUserTurn: false
31382
31606
  };
31383
31607
  if (this.settleTimer) {
31384
31608
  clearTimeout(this.settleTimer);
@@ -31386,110 +31610,23 @@ var require_dist2 = __commonJS({
31386
31610
  }
31387
31611
  this.responseEpoch += 1;
31388
31612
  this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
31389
- const startResponseTimeout = () => {
31390
- if (this.responseTimeout) clearTimeout(this.responseTimeout);
31391
- this.responseTimeout = setTimeout(() => {
31392
- if (this.isWaitingForResponse) this.finishResponse();
31393
- }, this.timeouts.maxResponse);
31394
- };
31395
31613
  await new Promise((resolve12, reject) => {
31396
31614
  let resolved = false;
31397
- const resolveOnce = () => {
31398
- if (resolved) return;
31399
- resolved = true;
31400
- resolve12();
31401
- };
31402
- const rejectOnce = (error48) => {
31403
- if (resolved) return;
31404
- this.resetPendingSendState("send_write_failed");
31405
- resolved = true;
31406
- reject(error48);
31407
- };
31408
- const writeRetryKey = (mode) => {
31409
- void this.writeToPty(this.sendKey).catch((error48) => {
31410
- LOG2.warn("CLI", `[${this.cliType}] ${mode} write failed: ${error48?.message || error48}`);
31411
- });
31412
- };
31413
- const submit = () => {
31414
- if (!this.ptyProcess) {
31415
- resolveOnce();
31416
- return;
31615
+ const completion = {
31616
+ resolveOnce: () => {
31617
+ if (resolved) return;
31618
+ resolved = true;
31619
+ resolve12();
31620
+ },
31621
+ rejectOnce: (error48) => {
31622
+ if (resolved) return;
31623
+ this.resetPendingSendState("send_write_failed");
31624
+ resolved = true;
31625
+ reject(error48);
31417
31626
  }
31418
- this.submitPendingUntil = 0;
31419
- const screenText = this.terminalScreen.getText();
31420
- this.recordTrace("submit_write", {
31421
- mode: "submit_key",
31422
- sendKey: this.sendKey,
31423
- screenText: summarizeCliTraceText(screenText, 500)
31424
- });
31425
- const retrySubmitIfStuck = (attempt) => {
31426
- this.submitRetryTimer = null;
31427
- if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
31428
- if (this.hasActionableApproval()) return;
31429
- if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
31430
- const screenText2 = this.terminalScreen.getText();
31431
- if (!promptLikelyVisible(screenText2, normalizedPromptSnippet)) return;
31432
- const liveApproval = this.runParseApproval(screenText2) || this.runParseApproval(this.recentOutputBuffer);
31433
- if (liveApproval) return;
31434
- const liveStatus = this.runDetectStatus(screenText2) || this.runDetectStatus(this.recentOutputBuffer);
31435
- if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
31436
- this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
31437
- LOG2.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
31438
- this.recordTrace("submit_write", {
31439
- mode: "submit_retry",
31440
- attempt,
31441
- sendKey: this.sendKey,
31442
- screenText: summarizeCliTraceText(screenText2, 500)
31443
- });
31444
- writeRetryKey("submit_retry");
31445
- if (attempt >= 3) {
31446
- this.submitRetryUsed = true;
31447
- return;
31448
- }
31449
- this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(attempt + 1), retryDelayMs);
31450
- };
31451
- void this.writeToPty(this.sendKey).then(() => {
31452
- commitUserTurn();
31453
- this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(1), retryDelayMs);
31454
- startResponseTimeout();
31455
- resolveOnce();
31456
- }, rejectOnce);
31457
31627
  };
31458
31628
  if (this.submitStrategy === "immediate") {
31459
- this.submitPendingUntil = 0;
31460
- this.recordTrace("submit_write", {
31461
- mode: "immediate",
31462
- text: summarizeCliTraceText(text, 500),
31463
- sendKey: this.sendKey,
31464
- screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
31465
- });
31466
- void this.writeToPty(text + this.sendKey).then(() => {
31467
- commitUserTurn();
31468
- this.submitRetryTimer = setTimeout(() => {
31469
- this.submitRetryTimer = null;
31470
- if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
31471
- if (this.hasActionableApproval()) return;
31472
- if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
31473
- const screenText = this.terminalScreen.getText();
31474
- if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
31475
- const liveApproval = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
31476
- if (liveApproval) return;
31477
- const liveStatus = this.runDetectStatus(screenText) || this.runDetectStatus(this.recentOutputBuffer);
31478
- if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
31479
- LOG2.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
31480
- this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
31481
- this.recordTrace("submit_write", {
31482
- mode: "immediate_retry",
31483
- attempt: 1,
31484
- sendKey: this.sendKey,
31485
- screenText: summarizeCliTraceText(screenText, 500)
31486
- });
31487
- writeRetryKey("immediate_retry");
31488
- this.submitRetryUsed = true;
31489
- }, retryDelayMs);
31490
- startResponseTimeout();
31491
- resolveOnce();
31492
- }, rejectOnce);
31629
+ this.submitImmediatePrompt(sendState, completion);
31493
31630
  return;
31494
31631
  }
31495
31632
  if (submitDelayMs > 0) {
@@ -31502,36 +31639,10 @@ var require_dist2 = __commonJS({
31502
31639
  screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
31503
31640
  });
31504
31641
  const submitStartedAt = Date.now();
31505
- let lastNormalizedScreen = "";
31506
- let lastScreenChangeAt = submitStartedAt;
31507
- const waitForEchoAndSubmit = () => {
31508
- if (!this.ptyProcess) {
31509
- resolveOnce();
31510
- return;
31511
- }
31512
- const now = Date.now();
31513
- const elapsed = now - submitStartedAt;
31514
- const screenText = this.terminalScreen.getText();
31515
- const normalizedScreen = normalizePromptText(screenText);
31516
- if (normalizedScreen !== lastNormalizedScreen) {
31517
- lastNormalizedScreen = normalizedScreen;
31518
- lastScreenChangeAt = now;
31519
- }
31520
- const echoVisible = !normalizedPromptSnippet || promptLikelyVisible(screenText, normalizedPromptSnippet);
31521
- if (echoVisible) {
31522
- const screenSettled = now - lastScreenChangeAt >= 500;
31523
- if (elapsed >= submitDelayMs && screenSettled) {
31524
- submit();
31525
- return;
31526
- }
31527
- }
31528
- if (elapsed >= maxEchoWaitMs) {
31529
- submit();
31530
- return;
31531
- }
31532
- setTimeout(waitForEchoAndSubmit, 50);
31533
- };
31534
- void this.writeToPty(text).then(() => waitForEchoAndSubmit(), rejectOnce);
31642
+ void this.writeToPty(text).then(
31643
+ () => this.waitForEchoAndSubmit(sendState, completion, submitStartedAt),
31644
+ completion.rejectOnce
31645
+ );
31535
31646
  });
31536
31647
  }
31537
31648
  getPartialResponse() {
@@ -31608,9 +31719,9 @@ var require_dist2 = __commonJS({
31608
31719
  shutdown() {
31609
31720
  this.clearIdleFinishCandidate("shutdown");
31610
31721
  this.clearAllTimers();
31611
- this.pendingOutputParseBuffer = "";
31722
+ this.pendingOutputParseChunks = [];
31612
31723
  this.pendingTerminalQueryTail = "";
31613
- this.ptyOutputBuffer = "";
31724
+ this.ptyOutputChunks = [];
31614
31725
  this.finishRetryCount = 0;
31615
31726
  if (this.ptyProcess) {
31616
31727
  this.ptyProcess.write("");
@@ -31631,9 +31742,9 @@ var require_dist2 = __commonJS({
31631
31742
  detach() {
31632
31743
  this.clearIdleFinishCandidate("detach");
31633
31744
  this.clearAllTimers();
31634
- this.pendingOutputParseBuffer = "";
31745
+ this.pendingOutputParseChunks = [];
31635
31746
  this.pendingTerminalQueryTail = "";
31636
- this.ptyOutputBuffer = "";
31747
+ this.ptyOutputChunks = [];
31637
31748
  this.finishRetryCount = 0;
31638
31749
  if (this.ptyProcess) {
31639
31750
  try {
@@ -31664,19 +31775,19 @@ var require_dist2 = __commonJS({
31664
31775
  clearTimeout(this.pendingOutputParseTimer);
31665
31776
  this.pendingOutputParseTimer = null;
31666
31777
  }
31667
- this.pendingOutputParseBuffer = "";
31778
+ this.pendingOutputParseChunks = [];
31668
31779
  this.pendingTerminalQueryTail = "";
31669
31780
  if (this.ptyOutputFlushTimer) {
31670
31781
  clearTimeout(this.ptyOutputFlushTimer);
31671
31782
  this.ptyOutputFlushTimer = null;
31672
31783
  }
31673
- this.ptyOutputBuffer = "";
31784
+ this.ptyOutputChunks = [];
31674
31785
  if (this.finishRetryTimer) {
31675
31786
  clearTimeout(this.finishRetryTimer);
31676
31787
  this.finishRetryTimer = null;
31677
31788
  }
31678
31789
  this.finishRetryCount = 0;
31679
- this.terminalScreen.reset();
31790
+ this.resetTerminalScreen();
31680
31791
  this.ptyProcess?.clearBuffer?.();
31681
31792
  this.onStatusChange?.();
31682
31793
  }
@@ -31793,7 +31904,7 @@ var require_dist2 = __commonJS({
31793
31904
  traceEntryCount: this.traceEntries.length,
31794
31905
  statusHistory: this.statusHistory.slice(-30),
31795
31906
  timeouts: this.timeouts,
31796
- pendingOutputParseBufferLength: this.pendingOutputParseBuffer.length,
31907
+ pendingOutputParseBufferLength: this.pendingOutputParseChunks.reduce((total, chunk) => total + chunk.length, 0),
31797
31908
  pendingOutputParseScheduled: !!this.pendingOutputParseTimer,
31798
31909
  ptyAlive: !!this.ptyProcess
31799
31910
  };
@@ -37468,14 +37579,14 @@ ${effect.notification.body || ""}`.trim();
37468
37579
  id: state.instanceId || state.type,
37469
37580
  parentId: null,
37470
37581
  providerType: state.type,
37471
- ...includeSessionMetadata && { providerName: state.name },
37582
+ providerName: state.name,
37472
37583
  kind: "workspace",
37473
37584
  transport: "cdp-page",
37474
37585
  status: normalizeManagedStatus(activeChat?.status || state.status, {
37475
37586
  activeModal: activeChat?.activeModal || null
37476
37587
  }),
37477
37588
  title,
37478
- ...includeSessionMetadata && { workspace: state.workspace || null },
37589
+ workspace: state.workspace || null,
37479
37590
  activeChat,
37480
37591
  ...summaryMetadata && { summaryMetadata },
37481
37592
  ...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES },
@@ -37500,7 +37611,7 @@ ${effect.notification.body || ""}`.trim();
37500
37611
  id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
37501
37612
  parentId: parent.instanceId || parent.type,
37502
37613
  providerType: ext.type,
37503
- ...includeSessionMetadata && { providerName: ext.name },
37614
+ providerName: ext.name,
37504
37615
  providerSessionId: ext.providerSessionId,
37505
37616
  kind: "agent",
37506
37617
  transport: "cdp-webview",
@@ -37508,7 +37619,7 @@ ${effect.notification.body || ""}`.trim();
37508
37619
  activeModal: activeChat?.activeModal || null
37509
37620
  }),
37510
37621
  title: activeChat?.title || ext.name,
37511
- ...includeSessionMetadata && { workspace: parent.workspace || null },
37622
+ workspace: parent.workspace || null,
37512
37623
  activeChat,
37513
37624
  ...summaryMetadata && { summaryMetadata },
37514
37625
  ...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES },
@@ -37548,7 +37659,7 @@ ${effect.notification.body || ""}`.trim();
37548
37659
  id: state.instanceId,
37549
37660
  parentId: null,
37550
37661
  providerType: state.type,
37551
- ...includeSessionMetadata && { providerName: state.name },
37662
+ providerName: state.name,
37552
37663
  providerSessionId: state.providerSessionId,
37553
37664
  kind: "agent",
37554
37665
  transport: "pty",
@@ -37556,7 +37667,7 @@ ${effect.notification.body || ""}`.trim();
37556
37667
  activeModal: activeChat?.activeModal || null
37557
37668
  }),
37558
37669
  title: activeChat?.title || state.name,
37559
- ...includeSessionMetadata && { workspace: state.workspace || null },
37670
+ workspace: state.workspace || null,
37560
37671
  ...includeRuntimeMetadata && {
37561
37672
  runtimeKey: state.runtime?.runtimeKey,
37562
37673
  runtimeDisplayName: state.runtime?.displayName,
@@ -37595,14 +37706,14 @@ ${effect.notification.body || ""}`.trim();
37595
37706
  id: state.instanceId,
37596
37707
  parentId: null,
37597
37708
  providerType: state.type,
37598
- ...includeSessionMetadata && { providerName: state.name },
37709
+ providerName: state.name,
37599
37710
  kind: "agent",
37600
37711
  transport: "acp",
37601
37712
  status: normalizeManagedStatus(activeChat?.status || state.status, {
37602
37713
  activeModal: activeChat?.activeModal || null
37603
37714
  }),
37604
37715
  title: activeChat?.title || state.name,
37605
- ...includeSessionMetadata && { workspace: state.workspace || null },
37716
+ workspace: state.workspace || null,
37606
37717
  activeChat,
37607
37718
  ...summaryMetadata && { summaryMetadata },
37608
37719
  ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
@@ -38031,26 +38142,26 @@ ${effect.notification.body || ""}`.trim();
38031
38142
  function shouldCollapseReadChatReplayDuplicate(message) {
38032
38143
  if (!message) return false;
38033
38144
  const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
38034
- if (role !== "assistant" && role !== "system") return false;
38035
- const kind = typeof message.kind === "string" ? message.kind.trim().toLowerCase() : "standard";
38036
- return kind === "tool" || kind === "terminal" || kind === "thought" || kind === "system";
38145
+ return role === "assistant" || role === "system";
38037
38146
  }
38038
38147
  function collapseReplayDuplicatesFromReadChat(messages) {
38039
38148
  const collapsed = [];
38040
- let lastReplayTurnSignature = "";
38149
+ const replaySignaturesInCurrentTurn = /* @__PURE__ */ new Set();
38041
38150
  for (const message of messages) {
38151
+ const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
38152
+ if (role === "user") {
38153
+ replaySignaturesInCurrentTurn.clear();
38154
+ }
38042
38155
  const signature = buildReadChatReplayCollapseSignature(message);
38043
38156
  const previous = collapsed[collapsed.length - 1];
38044
38157
  const previousSignature = buildReadChatReplayCollapseSignature(previous);
38045
38158
  if (shouldCollapseReadChatReplayDuplicate(message) && signature) {
38046
38159
  if (previousSignature === signature) continue;
38047
- if (lastReplayTurnSignature === signature) continue;
38160
+ if (replaySignaturesInCurrentTurn.has(signature)) continue;
38048
38161
  }
38049
38162
  collapsed.push(message);
38050
38163
  if (shouldCollapseReadChatReplayDuplicate(message) && signature) {
38051
- lastReplayTurnSignature = signature;
38052
- } else if ((message.role || "").toLowerCase() === "user") {
38053
- lastReplayTurnSignature = "";
38164
+ replaySignaturesInCurrentTurn.add(signature);
38054
38165
  }
38055
38166
  }
38056
38167
  return collapsed;
@@ -45505,6 +45616,18 @@ Run 'adhdev doctor' for detailed diagnostics.`
45505
45616
  const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human" && lastRole !== "system";
45506
45617
  return { unread, inboxBucket: unread ? "task_complete" : "idle" };
45507
45618
  }
45619
+ function projectLiveSessionFromFull(session) {
45620
+ const {
45621
+ capabilities: _capabilities,
45622
+ controlValues: _controlValues,
45623
+ providerControls: _providerControls,
45624
+ ...rest
45625
+ } = session;
45626
+ return {
45627
+ ...rest,
45628
+ activeChat: normalizeActiveChatData(session.activeChat, LIVE_STATUS_ACTIVE_CHAT_OPTIONS)
45629
+ };
45630
+ }
45508
45631
  function buildRecentLaunches(recentActivity) {
45509
45632
  return recentActivity.map((item) => ({
45510
45633
  id: item.id,
@@ -45529,7 +45652,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45529
45652
  options.cdpManagers,
45530
45653
  { profile: "full" }
45531
45654
  );
45532
- const sessions = profile === "full" ? unreadSourceSessions : buildSessionEntries(
45655
+ const sessions = profile === "full" ? unreadSourceSessions : profile === "live" ? unreadSourceSessions.map(projectLiveSessionFromFull) : buildSessionEntries(
45533
45656
  options.allStates,
45534
45657
  options.cdpManagers,
45535
45658
  { profile }
@@ -46809,10 +46932,6 @@ Run 'adhdev doctor' for detailed diagnostics.`
46809
46932
  LOG2.info("StatusReport", `\u2192${target} ${baseSummary}`);
46810
46933
  }
46811
46934
  }
46812
- const sessions = buildSessionEntries(
46813
- allStates,
46814
- this.deps.cdpManagers
46815
- );
46816
46935
  const payload = {
46817
46936
  ...buildStatusSnapshot2({
46818
46937
  allStates,
@@ -46832,9 +46951,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
46832
46951
  }),
46833
46952
  screenshotUsage: this.deps.getScreenshotUsage?.() || null
46834
46953
  };
46835
- const payloadBytes = JSON.stringify(payload).length;
46836
46954
  const p2pSent = this.sendP2PPayload(payload);
46837
46955
  if (p2pSent) {
46956
+ const payloadBytes = JSON.stringify(payload).length;
46838
46957
  LOG2.debug("P2P", `sent (${payloadBytes} bytes)`);
46839
46958
  if (payloadBytes > 256 * 1024) {
46840
46959
  LOG2.warn(
@@ -46844,8 +46963,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
46844
46963
  }
46845
46964
  }
46846
46965
  if (opts?.p2pOnly) return;
46966
+ if (!serverConnected || !serverConn) return;
46967
+ const payloadSessions = Array.isArray(payload.sessions) ? payload.sessions : [];
46847
46968
  const wsPayload = {
46848
- sessions: sessions.map((session) => ({
46969
+ sessions: payloadSessions.map((session) => ({
46849
46970
  id: session.id,
46850
46971
  parentId: session.parentId,
46851
46972
  providerType: session.providerType,
@@ -46871,8 +46992,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
46871
46992
  return;
46872
46993
  }
46873
46994
  this.lastServerStatusHash = wsHash;
46995
+ const wsPayloadBytes = JSON.stringify(wsPayload).length;
46874
46996
  serverConn.sendMessage("status_report", wsPayload);
46875
- LOG2.debug("Server", `sent status_report (${JSON.stringify(wsPayload).length} bytes)${opts?.reason ? ` [${opts.reason}]` : ""}`);
46997
+ LOG2.debug("Server", `sent status_report (${wsPayloadBytes} bytes)${opts?.reason ? ` [${opts.reason}]` : ""}`);
46876
46998
  }
46877
46999
  // ─── P2P ─────────────────────────────────────────
46878
47000
  sendP2PPayload(payload) {