@adhdev/daemon-core 0.9.63 → 0.9.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/chat/chat-signatures.d.ts +0 -4
  2. package/dist/chat/chat-signatures.js +0 -4
  3. package/dist/chat/chat-signatures.js.map +1 -1
  4. package/dist/chat/chat-signatures.mjs +0 -4
  5. package/dist/chat/chat-signatures.mjs.map +1 -1
  6. package/dist/chat/subscription-updates.d.ts +0 -2
  7. package/dist/cli-adapters/provider-cli-adapter.d.ts +2 -30
  8. package/dist/cli-adapters/provider-cli-parse.d.ts +1 -8
  9. package/dist/cli-adapters/provider-cli-shared.d.ts +8 -3
  10. package/dist/commands/chat-commands.d.ts +0 -2
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.js +646 -1687
  13. package/dist/index.js.map +1 -1
  14. package/dist/index.mjs +646 -1687
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/shared-types.d.ts +0 -7
  17. package/node_modules/@adhdev/session-host-core/package.json +1 -1
  18. package/package.json +1 -1
  19. package/src/chat/chat-signatures.ts +0 -8
  20. package/src/chat/subscription-updates.ts +7 -46
  21. package/src/cli-adapters/provider-cli-adapter.d.ts +2 -10
  22. package/src/cli-adapters/provider-cli-adapter.ts +66 -692
  23. package/src/cli-adapters/provider-cli-parse.d.ts +0 -7
  24. package/src/cli-adapters/provider-cli-parse.ts +2 -226
  25. package/src/cli-adapters/provider-cli-shared.d.ts +0 -1
  26. package/src/cli-adapters/provider-cli-shared.ts +8 -3
  27. package/src/commands/chat-commands.ts +54 -338
  28. package/src/daemon/dev-auto-implement.ts +3 -3
  29. package/src/daemon/dev-server.ts +3 -3
  30. package/src/index.d.ts +1 -1
  31. package/src/index.ts +0 -1
  32. package/src/launch.ts +10 -3
  33. package/src/providers/cli-provider-instance.ts +2 -39
  34. package/src/shared-types.d.ts +0 -7
  35. package/src/shared-types.ts +0 -8
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Required scripts in scripts/{version}/scripts.js:
8
8
  * - detectStatus(input) → AgentStatus string ('idle' | 'generating' | 'waiting_approval')
9
- * - parseOutput(input) → ReadChatResult { messages, status, activeModal, ... }
9
+ * - parseSession(input) → ReadChatResult { messages, status, activeModal, ... }
10
10
  * - parseApproval(input) → ModalInfo | null
11
11
  *
12
12
  * provider.json contract:
@@ -30,14 +30,11 @@ import {
30
30
  compactPromptText,
31
31
  estimatePromptDisplayLines,
32
32
  extractPromptRetrySnippet,
33
- getLastUserPromptText,
34
33
  listCliScriptNames,
35
- normalizeComparableMessageContent,
36
34
  normalizePromptText,
37
35
  normalizeScreenSnapshot,
38
36
  promptLikelyVisible,
39
37
  sanitizeTerminalText,
40
- trimPromptEchoPrefix,
41
38
  type CliChatMessage,
42
39
  type CliProviderModule,
43
40
  type CliScriptInput,
@@ -46,12 +43,9 @@ import {
46
43
  type CliTraceEntry,
47
44
  type ParsedSession,
48
45
  } from './provider-cli-shared.js';
49
- import { buildChatMessage } from '../providers/chat-message-normalization.js';
50
- import { validateReadChatResultPayload } from '../providers/read-chat-contract.js';
51
46
  import {
52
47
  buildCliParseInput,
53
48
  buildCliTraceParseSnapshot,
54
- hydrateCliParsedMessages,
55
49
  normalizeCliParsedMessages,
56
50
  summarizeCliTraceMessages,
57
51
  summarizeCliTraceText,
@@ -82,10 +76,6 @@ export {
82
76
  type CliTraceEntry,
83
77
  } from './provider-cli-shared.js';
84
78
 
85
- type SeedCliChatMessage = Omit<Partial<CliChatMessage>, 'role'> & {
86
- role?: string;
87
- content?: string;
88
- };
89
79
 
90
80
  interface IdleFinishCandidate {
91
81
  armedAt: number;
@@ -119,49 +109,6 @@ interface SendMessageCompletion {
119
109
  rejectOnce: (error: unknown) => void;
120
110
  }
121
111
 
122
- function normalizeComparableTranscriptText(value: unknown): string {
123
- return sanitizeTerminalText(String(value || ''))
124
- .replace(/\s+/g, ' ')
125
- .trim();
126
- }
127
-
128
- function hasVisibleInterruptPrompt(text: string): boolean {
129
- const interruptCopyPattern = /\bEnter\s+to\s+interrupt\b(?:\s*,?\s*Ctrl\s*(?:\+|-)?\s*C\s+to\s+cancel)?/i;
130
- return sanitizeTerminalText(text || '')
131
- .split(/\r?\n/g)
132
- .some((line) => {
133
- const trimmed = line.trim();
134
- if (!interruptCopyPattern.test(trimmed)) return false;
135
- return /^(?:[^A-Za-z0-9\s]{1,8}\s+)?[❯›>]\s+/.test(trimmed);
136
- });
137
- }
138
-
139
- function parsedTranscriptIsRicherThanCommitted(
140
- parsedMessages: Array<{ role?: string; content?: unknown; id?: string; index?: number }> | null | undefined,
141
- committedMessages: Array<{ role?: string; content?: unknown; id?: string; index?: number }> | null | undefined,
142
- ): boolean {
143
- if (!Array.isArray(parsedMessages) || !Array.isArray(committedMessages)) return false;
144
- if (parsedMessages.length > committedMessages.length) return true;
145
- if (parsedMessages.length !== committedMessages.length) return false;
146
-
147
- for (let index = 0; index < parsedMessages.length; index += 1) {
148
- const parsed = parsedMessages[index];
149
- const committed = committedMessages[index];
150
- if (!parsed || !committed) return false;
151
- if ((parsed.role || '') !== (committed.role || '')) return false;
152
- if (parsed.id && committed.id && String(parsed.id) !== String(committed.id)) return false;
153
- if (typeof parsed.index === 'number' && typeof committed.index === 'number' && parsed.index !== committed.index) return false;
154
-
155
- const parsedText = normalizeComparableTranscriptText(parsed.content);
156
- const committedText = normalizeComparableTranscriptText(committed.content);
157
- if (!parsedText || !committedText || parsedText === committedText) continue;
158
- if (parsedText.length > committedText.length && parsedText.startsWith(committedText)) return true;
159
- return false;
160
- }
161
-
162
- return false;
163
- }
164
-
165
112
  export function appendBoundedText(current: string, chunk: string, maxChars: number): string {
166
113
  if (!chunk) return current.length <= maxChars ? current : current.slice(-maxChars);
167
114
  if (maxChars <= 0) return '';
@@ -171,88 +118,6 @@ export function appendBoundedText(current: string, chunk: string, maxChars: numb
171
118
  return current.slice(-keepFromCurrent) + chunk;
172
119
  }
173
120
 
174
- const COMMITTED_ACTIVITY_PREFIX_BLOCK_RE = /^(?:📖|💻|🔎|📚|📋|✏️|📝|🔧|🛠️|⚙️)\s+(.+)$/;
175
-
176
- function isLikelyCommittedActivityPrefixContinuation(line: string): boolean {
177
- const trimmed = String(line || '').trim();
178
- if (!trimmed) return false;
179
- if (COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(trimmed)) return false;
180
- if (/\s/.test(trimmed)) return false;
181
- if (/[가-힣]/.test(trimmed)) return false;
182
- if (trimmed.length > 96) return false;
183
- return /^[A-Za-z0-9_./:@+%=-]+$/.test(trimmed);
184
- }
185
-
186
- function parseCommittedActivityPrefixBlock(lines: string[], index: number): { label: string; nextIndex: number } | null {
187
- const first = String(lines[index] || '').trim();
188
- if (!COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(first)) return null;
189
- const parts = [first];
190
- let nextIndex = index + 1;
191
- while (nextIndex < lines.length && isLikelyCommittedActivityPrefixContinuation(lines[nextIndex])) {
192
- parts.push(String(lines[nextIndex] || '').trim());
193
- nextIndex += 1;
194
- }
195
- return { label: parts.join(''), nextIndex };
196
- }
197
-
198
- export function sanitizeCliStandardMessageContent(content: unknown): string {
199
- const source = String(content || '').trim();
200
- if (!source) return '';
201
- const lines = source.split(/\r?\n/);
202
- if (lines.length < 4) return source;
203
-
204
- const counts = new Map<string, number>();
205
- for (let index = 0; index < lines.length; index += 1) {
206
- const block = parseCommittedActivityPrefixBlock(lines, index);
207
- if (!block) continue;
208
- counts.set(block.label, (counts.get(block.label) || 0) + 1);
209
- index = block.nextIndex - 1;
210
- }
211
-
212
- const repeatedLabels = new Set(
213
- Array.from(counts.entries())
214
- .filter(([, count]) => count >= 3)
215
- .map(([label]) => label),
216
- );
217
- if (repeatedLabels.size === 0) return source;
218
-
219
- const stripped: string[] = [];
220
- let removed = 0;
221
- for (let index = 0; index < lines.length; index += 1) {
222
- const block = parseCommittedActivityPrefixBlock(lines, index);
223
- if (block && repeatedLabels.has(block.label)) {
224
- removed += 1;
225
- index = block.nextIndex - 1;
226
- continue;
227
- }
228
- stripped.push(lines[index]);
229
- }
230
-
231
- const next = stripped.join('\n').replace(/\n{3,}/g, '\n\n').trim();
232
- return removed >= 3 && next.length >= 80 ? next : source;
233
- }
234
-
235
- function sanitizeCommittedMessageForDisplay<T extends { role?: string; kind?: string; content?: unknown }>(message: T): T {
236
- if (!message || message.role !== 'assistant' || (message.kind || 'standard') !== 'standard') return message;
237
- const content = sanitizeCliStandardMessageContent(message.content);
238
- if (content === message.content) return message;
239
- return { ...message, content };
240
- }
241
-
242
- export function trimLastAssistantEchoForCliMessages(messages: CliChatMessage[], prompt: string | undefined): void {
243
- if (!prompt) return;
244
- for (let index = messages.length - 1; index >= 0; index -= 1) {
245
- const message = messages[index];
246
- if (!message || message.role !== 'assistant' || typeof message.content !== 'string') continue;
247
- if ((message.kind || 'standard') !== 'standard') continue;
248
- message.content = trimPromptEchoPrefix(message.content, prompt);
249
- if (!message.content.trim()) {
250
- messages.splice(index, 1);
251
- }
252
- return;
253
- }
254
- }
255
-
256
121
  // ─── Adapter ────────────────────────────────────────
257
122
 
258
123
  export class ProviderCliAdapter implements CliAdapter {
@@ -263,11 +128,6 @@ export class ProviderCliAdapter implements CliAdapter {
263
128
  private provider: CliProviderModule;
264
129
  private ptyProcess: PtyRuntimeTransport | null = null;
265
130
  private transportFactory: PtyTransportFactory;
266
- private messages: CliChatMessage[] = [];
267
- private committedMessages: CliChatMessage[] = [];
268
- private structuredMessages: CliChatMessage[] = [];
269
- private committedMessagesActivitySignature = '';
270
- private committedMessagesChangedAt = 0;
271
131
  private currentStatus: CliSessionStatus['status'] = 'starting';
272
132
  private onStatusChange: (() => void) | null = null;
273
133
 
@@ -356,7 +216,6 @@ export class ProviderCliAdapter implements CliAdapter {
356
216
  private traceSeq = 0;
357
217
  private traceSessionId = '';
358
218
  private parsedStatusCache: {
359
- committedMessagesRef: CliChatMessage[];
360
219
  responseBuffer: string;
361
220
  currentTurnScope: TurnParseScope | null;
362
221
  recentOutputBuffer: string;
@@ -367,11 +226,8 @@ export class ProviderCliAdapter implements CliAdapter {
367
226
  cliName: string;
368
227
  result: any;
369
228
  } | null = null;
370
- private lastStatusHotPathParseAt = Number.NEGATIVE_INFINITY;
371
- private static readonly STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS = 1000;
372
229
  private static readonly SCREEN_SNAPSHOT_MIN_INTERVAL_MS = 250;
373
230
  private static readonly MAX_TRACE_ENTRIES = 250;
374
- private static readonly PARSE_MESSAGE_TAIL_LIMIT = 100;
375
231
 
376
232
  private readonly providerResolutionMeta: ProviderResolutionMeta;
377
233
  private static readonly FINISH_RETRY_DELAY_MS = 300;
@@ -398,37 +254,6 @@ export class ProviderCliAdapter implements CliAdapter {
398
254
  return Math.max(0, (previousLength + appendedLength) - nextLength);
399
255
  }
400
256
 
401
- private buildCommittedMessagesActivitySignature(): string {
402
- const last = this.committedMessages[this.committedMessages.length - 1];
403
- return [
404
- String(this.committedMessages.length),
405
- String(last?.role || ''),
406
- String(last?.kind || ''),
407
- String(last?.senderName || ''),
408
- String(last?.timestamp || ''),
409
- String(last?.receivedAt || ''),
410
- normalizeComparableMessageContent(last?.content || '').slice(-240),
411
- ].join('|');
412
- }
413
-
414
- private syncMessageViews(): void {
415
- const signature = this.buildCommittedMessagesActivitySignature();
416
- if (signature !== this.committedMessagesActivitySignature) {
417
- this.committedMessagesActivitySignature = signature;
418
- this.committedMessagesChangedAt = Date.now();
419
- }
420
- this.messages = [...this.committedMessages];
421
- this.structuredMessages = [...this.committedMessages];
422
- }
423
-
424
- getLastCommittedMessageActivityAt(): number {
425
- const last = this.committedMessages[this.committedMessages.length - 1];
426
- const messageTime = Math.max(
427
- typeof last?.receivedAt === 'number' && Number.isFinite(last.receivedAt) ? last.receivedAt : 0,
428
- typeof last?.timestamp === 'number' && Number.isFinite(last.timestamp) ? last.timestamp : 0,
429
- );
430
- return Math.max(messageTime, this.committedMessagesChangedAt || 0);
431
- }
432
257
 
433
258
  private readTerminalScreenText(now = Date.now()): string {
434
259
  const screenText = this.terminalScreen.getText() || '';
@@ -454,7 +279,6 @@ export class ProviderCliAdapter implements CliAdapter {
454
279
  const cached = this.parsedStatusCache;
455
280
  if (
456
281
  cached
457
- && cached.committedMessagesRef === this.committedMessages
458
282
  && cached.responseBuffer === this.responseBuffer
459
283
  && cached.currentTurnScope === this.currentTurnScope
460
284
  && cached.recentOutputBuffer === this.recentOutputBuffer
@@ -477,58 +301,6 @@ export class ProviderCliAdapter implements CliAdapter {
477
301
  return this.providerOwnsTranscript() && this.provider.transcriptContext === 'full';
478
302
  }
479
303
 
480
- private selectParseBaseMessages(baseMessages: CliChatMessage[]): CliChatMessage[] {
481
- if (this.shouldUseFullProviderTranscriptContext()) return baseMessages;
482
- if (baseMessages.length <= ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
483
- return baseMessages.slice(-ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
484
- }
485
-
486
- private messagesShareStableIdentity(left: any, right: any): boolean {
487
- if (left === right) return true;
488
- if (!left || !right) return false;
489
- if ((left.role || '') !== (right.role || '')) return false;
490
- if (left.id && right.id && String(left.id) === String(right.id)) return true;
491
- if (typeof left.index === 'number' && typeof right.index === 'number' && left.index === right.index) return true;
492
- return false;
493
- }
494
-
495
- private messagesComparable(left: any, right: any): boolean {
496
- if (this.messagesShareStableIdentity(left, right)) return true;
497
- if (!left || !right) return false;
498
- if ((left.role || '') !== (right.role || '')) return false;
499
- const leftText = normalizeComparableTranscriptText(left.content);
500
- const rightText = normalizeComparableTranscriptText(right.content);
501
- return !!leftText && leftText === rightText;
502
- }
503
-
504
- private stitchParsedMessagesWithCommittedBase(
505
- parsedMessages: any[],
506
- fullBaseMessages: CliChatMessage[],
507
- parseBaseMessages: CliChatMessage[],
508
- ): any[] {
509
- if (!Array.isArray(parsedMessages) || parsedMessages.length === 0) return parsedMessages;
510
- if (fullBaseMessages.length <= parseBaseMessages.length) return parsedMessages;
511
-
512
- const parsedFirst = parsedMessages[0];
513
- const fullFirst = fullBaseMessages[0];
514
- if (parsedMessages.length >= fullBaseMessages.length && this.messagesComparable(parsedFirst, fullFirst)) {
515
- return parsedMessages;
516
- }
517
-
518
- const tailFirst = parseBaseMessages[0];
519
- if (tailFirst && this.messagesComparable(parsedFirst, tailFirst)) {
520
- const prefixLength = fullBaseMessages.length - parseBaseMessages.length;
521
- const prefix = fullBaseMessages.slice(0, prefixLength);
522
- const shouldSanitizePrefix = !!this.currentTurnScope || this.currentStatus !== 'idle' || !!this.activeModal;
523
- const nextPrefix = shouldSanitizePrefix
524
- ? prefix.map((message) => sanitizeCommittedMessageForDisplay(message))
525
- : prefix;
526
- return [...nextPrefix, ...parsedMessages];
527
- }
528
-
529
- return [...fullBaseMessages, ...parsedMessages];
530
- }
531
-
532
304
  private getIdleFinishConfirmMs(): number {
533
305
  return this.timeouts.idleFinishConfirm;
534
306
  }
@@ -1102,10 +874,6 @@ export class ProviderCliAdapter implements CliAdapter {
1102
874
  );
1103
875
  }
1104
876
 
1105
- private trimLastAssistantEcho(messages: CliChatMessage[], prompt: string | undefined): void {
1106
- trimLastAssistantEchoForCliMessages(messages, prompt);
1107
- }
1108
-
1109
877
  private clearAllTimers(): void {
1110
878
  if (this.responseTimeout) { clearTimeout(this.responseTimeout); this.responseTimeout = null; }
1111
879
  if (this.idleTimeout) { clearTimeout(this.idleTimeout); this.idleTimeout = null; }
@@ -1193,10 +961,10 @@ export class ProviderCliAdapter implements CliAdapter {
1193
961
  const session = this.runParseSession();
1194
962
  if (!session) return;
1195
963
 
1196
- const { status, messages, modal, parsedStatus } = session;
964
+ const { status, messages, parsedStatus } = session;
965
+ const modal = (session as any).activeModal ?? session.modal ?? null;
1197
966
  const parsedMessages = normalizeCliParsedMessages(messages, {
1198
- committedMessages: this.committedMessages,
1199
- scope: this.currentTurnScope,
967
+ scope: null,
1200
968
  lastOutputAt: this.lastOutputAt,
1201
969
  });
1202
970
 
@@ -1396,7 +1164,7 @@ export class ProviderCliAdapter implements CliAdapter {
1396
1164
  const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(effectiveScreenText);
1397
1165
  const parsedShowsLiveAssistantProgress = parsedStatus === 'generating'
1398
1166
  && !!lastParsedAssistant
1399
- && parsedMessages.length > this.committedMessages.length;
1167
+ ;
1400
1168
  if (prevStatus === 'idle' && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
1401
1169
  return;
1402
1170
  }
@@ -1573,10 +1341,7 @@ export class ProviderCliAdapter implements CliAdapter {
1573
1341
  const visibleAssistant = [...parsedMessages].reverse().find((m) => m.role === 'assistant' && m.content.trim());
1574
1342
  if (!visibleAssistant) return false;
1575
1343
 
1576
- this.committedMessages = parsedMessages;
1577
- this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
1578
1344
  this.clearAllTimers();
1579
- this.syncMessageViews();
1580
1345
  this.responseBuffer = '';
1581
1346
  this.isWaitingForResponse = false;
1582
1347
  this.responseSettleIgnoreUntil = 0;
@@ -1588,7 +1353,7 @@ export class ProviderCliAdapter implements CliAdapter {
1588
1353
  this.setStatus('idle', 'script_idle_commit');
1589
1354
  this.onStatusChange?.();
1590
1355
  this.recordTrace('script_idle_commit', {
1591
- messageCount: this.committedMessages.length,
1356
+ messageCount: parsedMessages.length,
1592
1357
  lastAssistant: summarizeCliTraceText(visibleAssistant.content, 320),
1593
1358
  });
1594
1359
  return true;
@@ -1596,30 +1361,27 @@ export class ProviderCliAdapter implements CliAdapter {
1596
1361
 
1597
1362
  private commitCurrentTranscript(): { hasAssistant: boolean; assistantContent: string } {
1598
1363
  const parsed = this.parseCurrentTranscript(
1599
- this.committedMessages,
1364
+ [],
1600
1365
  this.responseBuffer,
1601
1366
  this.currentTurnScope,
1602
1367
  );
1603
1368
  if (parsed && Array.isArray(parsed.messages)) {
1604
- this.committedMessages = normalizeCliParsedMessages(parsed.messages, {
1605
- committedMessages: this.committedMessages,
1606
- scope: this.currentTurnScope,
1369
+ const parsedMessages = normalizeCliParsedMessages(parsed.messages, {
1370
+ scope: null,
1607
1371
  lastOutputAt: this.lastOutputAt,
1608
1372
  });
1609
- this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
1610
- this.syncMessageViews();
1611
- const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === 'assistant');
1373
+ const lastAssistant = [...parsedMessages].reverse().find((message) => message.role === 'assistant');
1612
1374
  if (this.currentTurnScope) {
1613
1375
  LOG.info(
1614
1376
  'CLI',
1615
- `[${this.cliType}] commitCurrentTranscript committedMessages=${this.committedMessages.length} finalLastAssistant=${JSON.stringify(summarizeCliTraceText(lastAssistant?.content || '', 220)).slice(0, 260)}`
1377
+ `[${this.cliType}] commitCurrentTranscript parserMessages=${parsedMessages.length} finalLastAssistant=${JSON.stringify(summarizeCliTraceText(lastAssistant?.content || '', 220)).slice(0, 260)}`
1616
1378
  );
1617
1379
  }
1618
1380
  this.recordTrace('commit_transcript', {
1619
1381
  parsedStatus: parsed.status || null,
1620
- messageCount: this.committedMessages.length,
1382
+ messageCount: parsedMessages.length,
1621
1383
  lastAssistant: lastAssistant ? summarizeCliTraceText(lastAssistant.content, 320) : '',
1622
- messages: summarizeCliTraceMessages(this.committedMessages),
1384
+ messages: summarizeCliTraceMessages(parsedMessages),
1623
1385
  ...buildCliTraceParseSnapshot({
1624
1386
  accumulatedBuffer: this.accumulatedBuffer,
1625
1387
  accumulatedRawBuffer: this.accumulatedRawBuffer,
@@ -1656,71 +1418,31 @@ export class ProviderCliAdapter implements CliAdapter {
1656
1418
  // ─── Script Execution ──────────────────────────
1657
1419
 
1658
1420
  private runParseSession(): ParsedSession | null {
1659
- // Preferred: provider exposes a unified parseSession script
1660
- if (typeof this.cliScripts?.parseSession === 'function') {
1661
- try {
1662
- const screenText = this.terminalScreen.getText();
1663
- const tail = this.recentOutputBuffer.slice(-500);
1664
- const parseBaseMessages = this.selectParseBaseMessages(this.committedMessages);
1665
- const input = buildCliParseInput({
1666
- accumulatedBuffer: this.accumulatedBuffer,
1667
- accumulatedRawBuffer: this.accumulatedRawBuffer,
1668
- recentOutputBuffer: this.recentOutputBuffer,
1669
- terminalScreenText: screenText,
1670
- baseMessages: parseBaseMessages,
1671
- partialResponse: this.responseBuffer,
1672
- isWaitingForResponse: this.isWaitingForResponse,
1673
- scope: this.currentTurnScope,
1674
- runtimeSettings: this.runtimeSettings,
1675
- });
1676
- const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
1677
- if (session && typeof session === 'object' && Array.isArray(session.messages)) {
1678
- session.messages = this.stitchParsedMessagesWithCommittedBase(
1679
- session.messages,
1680
- this.committedMessages,
1681
- parseBaseMessages,
1682
- );
1683
- }
1684
- this.parseErrorMessage = null;
1685
- return session && typeof session === 'object' ? session : null;
1686
- } catch (e: any) {
1687
- const message = e?.message || String(e);
1688
- this.parseErrorMessage = message;
1689
- LOG.warn('CLI', `[${this.cliType}] parseSession error: ${message}`);
1690
- return null;
1691
- }
1421
+ if (typeof this.cliScripts?.parseSession !== 'function') {
1422
+ this.parseErrorMessage = `${this.cliType} parseSession unavailable`;
1423
+ return null;
1692
1424
  }
1693
- // Fallback: reconcile from the three individual scripts (for providers without parseSession)
1694
- if (!this.cliScripts?.detectStatus && !this.cliScripts?.parseOutput) return null;
1695
1425
  try {
1696
- const tail = this.settledBuffer;
1697
- const parsedTranscript = this.parseCurrentTranscript(
1698
- this.committedMessages,
1699
- this.responseBuffer,
1700
- this.currentTurnScope,
1701
- );
1702
- const parsedModal = parsedTranscript?.activeModal
1703
- && Array.isArray(parsedTranscript.activeModal.buttons)
1704
- && parsedTranscript.activeModal.buttons.some((b: any) => typeof b === 'string' && b.trim())
1705
- ? parsedTranscript.activeModal
1706
- : null;
1707
- const approval = this.runParseApproval(tail);
1708
- const modal = approval || parsedModal;
1709
- const rawStatus = this.runDetectStatus(tail);
1710
- const parsedStatus = typeof parsedTranscript?.status === 'string' ? parsedTranscript.status : null;
1711
- const effectiveStatus = (parsedStatus === 'waiting_approval' && modal)
1712
- ? 'waiting_approval'
1713
- : (rawStatus || parsedStatus || 'idle');
1714
- return {
1715
- status: effectiveStatus,
1716
- messages: Array.isArray(parsedTranscript?.messages) ? parsedTranscript.messages : [],
1717
- modal,
1718
- parsedStatus,
1719
- };
1426
+ const screenText = this.terminalScreen.getText();
1427
+ const tail = this.recentOutputBuffer.slice(-500);
1428
+ const input = buildCliParseInput({
1429
+ accumulatedBuffer: this.accumulatedBuffer,
1430
+ accumulatedRawBuffer: this.accumulatedRawBuffer,
1431
+ recentOutputBuffer: this.recentOutputBuffer,
1432
+ terminalScreenText: screenText,
1433
+ baseMessages: [],
1434
+ partialResponse: this.responseBuffer,
1435
+ isWaitingForResponse: this.isWaitingForResponse,
1436
+ scope: this.currentTurnScope,
1437
+ runtimeSettings: this.runtimeSettings,
1438
+ });
1439
+ const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
1440
+ this.parseErrorMessage = null;
1441
+ return session && typeof session === 'object' ? session : null;
1720
1442
  } catch (e: any) {
1721
1443
  const message = e?.message || String(e);
1722
1444
  this.parseErrorMessage = message;
1723
- LOG.warn('CLI', `[${this.cliType}] parseSession fallback error: ${message}`);
1445
+ LOG.warn('CLI', `[${this.cliType}] parseSession error: ${message}`);
1724
1446
  return null;
1725
1447
  }
1726
1448
  }
@@ -1775,41 +1497,6 @@ export class ProviderCliAdapter implements CliAdapter {
1775
1497
  return this.currentStatus;
1776
1498
  }
1777
1499
 
1778
- private suppressStaleParsedApproval(
1779
- parsed: any,
1780
- recentBuffer: string,
1781
- screenText: string,
1782
- ): any {
1783
- const actionableParsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons)
1784
- && parsed.activeModal.buttons.some((button: any) => typeof button === 'string' && button.trim())
1785
- ? parsed.activeModal
1786
- : null;
1787
- if (!parsed || parsed?.status !== 'waiting_approval' || !actionableParsedModal) {
1788
- return parsed;
1789
- }
1790
-
1791
- const inApprovalCooldown = this.lastApprovalResolvedAt > 0
1792
- && (Date.now() - this.lastApprovalResolvedAt) < this.timeouts.approvalCooldown;
1793
- if (!inApprovalCooldown) {
1794
- return parsed;
1795
- }
1796
-
1797
- const visibleModal = this.runParseApproval(recentBuffer);
1798
- if (visibleModal) {
1799
- return parsed;
1800
- }
1801
-
1802
- const detectedStatus = this.runDetectStatus(recentBuffer);
1803
- const resolvedStatus = detectedStatus && detectedStatus !== 'waiting_approval'
1804
- ? detectedStatus
1805
- : ((this.isWaitingForResponse || this.currentTurnScope) ? 'generating' : (this.currentStatus === 'waiting_approval' ? 'idle' : this.currentStatus));
1806
- return {
1807
- ...parsed,
1808
- status: resolvedStatus,
1809
- activeModal: null,
1810
- };
1811
- }
1812
-
1813
1500
  // ─── Public API (CliAdapter) ───────────────────
1814
1501
 
1815
1502
  getStatus(options: { allowParse?: boolean } = {}): CliSessionStatus {
@@ -1817,19 +1504,8 @@ export class ProviderCliAdapter implements CliAdapter {
1817
1504
  const startupModal = allowParse && this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
1818
1505
  let effectiveStatus = this.projectEffectiveStatus(startupModal);
1819
1506
  let effectiveModal = startupModal || this.activeModal;
1820
- if (allowParse && !startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === 'function') {
1821
- let parsed = this.getFreshParsedStatusCache();
1822
- if (!parsed && effectiveStatus !== 'idle') {
1823
- const now = Date.now();
1824
- if ((now - this.lastStatusHotPathParseAt) >= ProviderCliAdapter.STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS) {
1825
- this.lastStatusHotPathParseAt = now;
1826
- try {
1827
- parsed = this.getScriptParsedStatus();
1828
- } catch {
1829
- // Ignore parse errors here; getScriptParsedStatus surfaces them on richer callers.
1830
- }
1831
- }
1832
- }
1507
+ if (allowParse && !startupModal && !effectiveModal) {
1508
+ const parsed = this.getFreshParsedStatusCache();
1833
1509
  const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons)
1834
1510
  && parsed.activeModal.buttons.some((button: any) => typeof button === 'string' && button.trim())
1835
1511
  ? parsed.activeModal
@@ -1842,7 +1518,7 @@ export class ProviderCliAdapter implements CliAdapter {
1842
1518
  const bufferState = this.getBufferState();
1843
1519
  return {
1844
1520
  status: effectiveStatus,
1845
- messages: [...this.committedMessages],
1521
+ messages: [],
1846
1522
  workingDir: this.workingDir,
1847
1523
  activeModal: effectiveModal,
1848
1524
  errorMessage: this.parseErrorMessage || undefined,
@@ -1851,119 +1527,6 @@ export class ProviderCliAdapter implements CliAdapter {
1851
1527
  };
1852
1528
  }
1853
1529
 
1854
- seedCommittedMessages(messages: SeedCliChatMessage[]): void {
1855
- const normalized = (Array.isArray(messages) ? messages : [])
1856
- .filter((message) => message && (message.role === 'user' || message.role === 'assistant'))
1857
- .map((message) => ({
1858
- role: message.role as 'user' | 'assistant',
1859
- content: typeof message.content === 'string' ? message.content : String(message.content || ''),
1860
- timestamp: typeof message.timestamp === 'number' && Number.isFinite(message.timestamp)
1861
- ? message.timestamp
1862
- : undefined,
1863
- receivedAt: typeof message.receivedAt === 'number' && Number.isFinite(message.receivedAt)
1864
- ? message.receivedAt
1865
- : undefined,
1866
- kind: typeof message.kind === 'string' ? message.kind : undefined,
1867
- id: typeof message.id === 'string' ? message.id : undefined,
1868
- index: typeof message.index === 'number' ? message.index : undefined,
1869
- providerUnitKey: typeof (message as any).providerUnitKey === 'string' ? (message as any).providerUnitKey : undefined,
1870
- bubbleId: typeof (message as any).bubbleId === 'string' ? (message as any).bubbleId : undefined,
1871
- bubbleState: typeof (message as any).bubbleState === 'string' ? (message as any).bubbleState : undefined,
1872
- _turnKey: typeof (message as any)._turnKey === 'string' ? (message as any)._turnKey : undefined,
1873
- meta: message.meta && typeof message.meta === 'object' ? { ...(message.meta as Record<string, any>) } : undefined,
1874
- senderName: typeof message.senderName === 'string' ? message.senderName : undefined,
1875
- }));
1876
- this.committedMessages = normalized;
1877
- this.syncMessageViews();
1878
- }
1879
-
1880
- private getSharedCommittedPrefixLength(parsedMessages: any[]): number {
1881
- const committedMessages = this.committedMessages;
1882
- const max = Math.min(parsedMessages.length, committedMessages.length);
1883
- let index = 0;
1884
- while (index < max && this.messagesShareStableIdentity(parsedMessages[index], committedMessages[index])) {
1885
- index += 1;
1886
- }
1887
- return index;
1888
- }
1889
-
1890
- private hydrateCommittedPrefixForParsedStatus(parsedMessages: any[]): any[] | null {
1891
- const sharedPrefixLength = this.getSharedCommittedPrefixLength(parsedMessages);
1892
- if (sharedPrefixLength !== this.committedMessages.length) return null;
1893
-
1894
- const committedHydratedMessages = this.committedMessages.map((message, index) => {
1895
- const timestamp = typeof message.timestamp === 'number' && Number.isFinite(message.timestamp)
1896
- ? message.timestamp
1897
- : (this.lastOutputAt || this.currentTurnScope?.startedAt || Date.now());
1898
- const contentValue = message.content;
1899
- return {
1900
- role: message.role,
1901
- content: typeof contentValue === 'string' ? contentValue : String(contentValue || ''),
1902
- timestamp,
1903
- receivedAt: typeof message.receivedAt === 'number' && Number.isFinite(message.receivedAt)
1904
- ? message.receivedAt
1905
- : timestamp,
1906
- kind: message.kind,
1907
- id: message.id || `msg_${index}`,
1908
- index: typeof message.index === 'number' ? message.index : index,
1909
- providerUnitKey: (message as any).providerUnitKey,
1910
- bubbleId: (message as any).bubbleId,
1911
- bubbleState: (message as any).bubbleState,
1912
- _turnKey: (message as any)._turnKey,
1913
- meta: message.meta,
1914
- senderName: message.senderName,
1915
- };
1916
- });
1917
- const extraMessages = parsedMessages.slice(sharedPrefixLength);
1918
- if (extraMessages.length === 0) return committedHydratedMessages;
1919
-
1920
- const extraHydratedMessages = hydrateCliParsedMessages(extraMessages, {
1921
- committedMessages: [],
1922
- scope: this.currentTurnScope,
1923
- lastOutputAt: this.lastOutputAt,
1924
- }).map((message, offset) => ({
1925
- ...message,
1926
- id: message.id || `msg_${sharedPrefixLength + offset}`,
1927
- index: typeof message.index === 'number' ? message.index : sharedPrefixLength + offset,
1928
- }));
1929
- return [...committedHydratedMessages, ...extraHydratedMessages];
1930
- }
1931
-
1932
- private hydrateParsedMessagesForStatus(parsedMessages: any[]): any[] {
1933
- return this.hydrateCommittedPrefixForParsedStatus(parsedMessages)
1934
- || hydrateCliParsedMessages(parsedMessages, {
1935
- committedMessages: this.committedMessages,
1936
- scope: this.currentTurnScope,
1937
- lastOutputAt: this.lastOutputAt,
1938
- });
1939
- }
1940
-
1941
- private buildCommittedChatMessages(): any[] {
1942
- return this.committedMessages.map((message, index) => {
1943
- const rawContentValue = message.content;
1944
- const rawContent = typeof rawContentValue === 'string' ? rawContentValue : String(rawContentValue || '');
1945
- const content = message.role === 'assistant' && (message.kind || 'standard') === 'standard'
1946
- ? sanitizeCliStandardMessageContent(rawContent)
1947
- : rawContent;
1948
- return buildChatMessage({
1949
- role: message.role,
1950
- content,
1951
- timestamp: message.timestamp,
1952
- kind: message.kind,
1953
- meta: message.meta,
1954
- senderName: message.senderName,
1955
- id: message.id || `msg_${index}`,
1956
- index: typeof message.index === 'number' ? message.index : index,
1957
- providerUnitKey: (message as any).providerUnitKey,
1958
- bubbleId: (message as any).bubbleId,
1959
- bubbleState: (message as any).bubbleState,
1960
- _turnKey: (message as any)._turnKey,
1961
- receivedAt: typeof message.receivedAt === 'number'
1962
- ? message.receivedAt
1963
- : message.timestamp,
1964
- });
1965
- });
1966
- }
1967
1530
 
1968
1531
  /**
1969
1532
  * Script-based full parse — returns ReadChatResult.
@@ -1974,7 +1537,6 @@ export class ProviderCliAdapter implements CliAdapter {
1974
1537
  const cached = this.parsedStatusCache;
1975
1538
  if (
1976
1539
  cached
1977
- && cached.committedMessagesRef === this.committedMessages
1978
1540
  && cached.responseBuffer === this.responseBuffer
1979
1541
  && cached.currentTurnScope === this.currentTurnScope
1980
1542
  && cached.recentOutputBuffer === this.recentOutputBuffer
@@ -1987,163 +1549,33 @@ export class ProviderCliAdapter implements CliAdapter {
1987
1549
  return cached.result;
1988
1550
  }
1989
1551
 
1990
- const parsed = this.parseCurrentTranscript(
1991
- this.committedMessages,
1992
- this.responseBuffer,
1993
- this.currentTurnScope,
1994
- screenText,
1995
- );
1996
- const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons)
1997
- && parsed.activeModal.buttons.some((button: any) => typeof button === 'string' && button.trim())
1998
- ? parsed.activeModal
1999
- : null;
2000
- if (parsedModal && parsed?.status === 'waiting_approval') {
2001
- this.activeModal = parsedModal;
2002
- this.isWaitingForResponse = true;
2003
- if (this.currentStatus !== 'waiting_approval') {
2004
- this.setStatus('waiting_approval', 'parsed_waiting_approval');
2005
- this.onStatusChange?.();
2006
- }
2007
- }
2008
- if (parsed && Array.isArray(parsed.messages) && this.provider.allowInputDuringGeneration === true) {
2009
- const hydratedForCommit = normalizeCliParsedMessages(parsed.messages, {
2010
- committedMessages: this.committedMessages,
2011
- scope: this.currentTurnScope,
2012
- lastOutputAt: this.lastOutputAt,
2013
- });
2014
- const fakeSession: ParsedSession = {
2015
- status: parsed.status || 'idle',
2016
- messages: parsed.messages,
2017
- modal: parsedModal,
2018
- parsedStatus: parsed.status || null,
2019
- };
2020
- if (this.maybeCommitVisibleIdleTranscript(fakeSession, hydratedForCommit)) {
2021
- return this.getScriptParsedStatus();
2022
- }
2023
- }
2024
- const shouldPreferCommittedMessages =
2025
- !this.currentTurnScope
2026
- && !this.activeModal
2027
- && this.currentStatus === 'idle';
2028
- let result: any;
2029
- if (parsed && Array.isArray(parsed.messages)) {
2030
- const parsedHydratedMessages = this.hydrateParsedMessagesForStatus(parsed.messages);
2031
- const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === 'assistant' && typeof message.content === 'string' && message.content.trim());
2032
- const shouldAdoptParsedIdleReplay =
2033
- !this.currentTurnScope
2034
- && !this.activeModal
2035
- && !!parsedLastAssistant
2036
- && parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages, this.committedMessages)
2037
- && (
2038
- this.currentStatus === 'idle'
2039
- || (
2040
- this.currentStatus === 'generating'
2041
- && this.isWaitingForResponse
2042
- && parsed.status === 'idle'
2043
- && this.runDetectStatus(this.recentOutputBuffer) === 'idle'
2044
- )
2045
- );
2046
- if (shouldAdoptParsedIdleReplay) {
2047
- this.committedMessages = this.getSharedCommittedPrefixLength(parsed.messages) === this.committedMessages.length
2048
- ? parsedHydratedMessages.map((message) => ({
2049
- role: message.role,
2050
- content: typeof message.content === 'string' ? message.content : String(message.content || ''),
2051
- timestamp: message.timestamp,
2052
- receivedAt: message.receivedAt,
2053
- kind: message.kind,
2054
- id: message.id,
2055
- index: message.index,
2056
- meta: message.meta,
2057
- senderName: message.senderName,
2058
- }))
2059
- : normalizeCliParsedMessages(parsed.messages, {
2060
- committedMessages: this.committedMessages,
2061
- scope: this.currentTurnScope,
2062
- lastOutputAt: this.lastOutputAt,
2063
- });
2064
- this.syncMessageViews();
2065
- if (this.currentStatus !== 'idle' || this.isWaitingForResponse) {
2066
- this.responseBuffer = '';
2067
- this.isWaitingForResponse = false;
2068
- this.responseSettleIgnoreUntil = 0;
2069
- this.submitRetryUsed = false;
2070
- this.submitRetryPromptSnippet = '';
2071
- this.finishRetryCount = 0;
2072
- this.currentTurnScope = null;
2073
- this.activeModal = null;
2074
- this.setStatus('idle', 'parsed_idle_replay_commit');
2075
- this.onStatusChange?.();
2076
- }
2077
- }
2078
- const shouldPreferCommittedHistoryReplay =
2079
- !this.currentTurnScope
2080
- && !this.activeModal
2081
- && this.committedMessages.length > parsedHydratedMessages.length;
2082
- const shouldPreferCommittedIdleReplay =
2083
- shouldPreferCommittedMessages
2084
- && !shouldAdoptParsedIdleReplay;
2085
- const hydratedMessages = (shouldPreferCommittedIdleReplay || shouldPreferCommittedHistoryReplay)
2086
- ? this.buildCommittedChatMessages()
2087
- : parsedHydratedMessages;
2088
- result = {
2089
- id: parsed.id || 'cli_session',
2090
- status: parsed.status || this.currentStatus,
2091
- title: parsed.title || this.cliName,
2092
- messages: hydratedMessages,
2093
- activeModal: parsed.activeModal ?? this.activeModal,
2094
- providerSessionId: typeof parsed.providerSessionId === 'string' ? parsed.providerSessionId : undefined,
2095
- ...(this.getBufferState() ? { bufferState: this.getBufferState() } : {}),
2096
- ...(this.providerOwnsTranscript() ? { transcriptAuthority: 'provider', coverage: this.shouldUseFullProviderTranscriptContext() ? 'full' : 'tail' } : {}),
2097
- };
2098
- } else {
2099
- const messages = [...this.committedMessages];
2100
- const bufferState = this.getBufferState();
2101
- result = {
2102
- id: 'cli_session',
2103
- status: this.currentStatus,
2104
- title: this.cliName,
2105
- messages: messages.map((message, index) => buildChatMessage({
2106
- ...message,
2107
- id: message.id || `msg_${index}`,
2108
- index: typeof message.index === 'number' ? message.index : index,
2109
- receivedAt: typeof message.receivedAt === 'number'
2110
- ? message.receivedAt
2111
- : message.timestamp,
2112
- })),
2113
- activeModal: this.activeModal,
2114
- ...(bufferState ? { bufferState } : {}),
2115
- };
1552
+ const parsed = this.runParseSession();
1553
+ if (!parsed || !Array.isArray(parsed.messages)) {
1554
+ throw new Error(this.parseErrorMessage || `${this.cliType} parseSession did not return messages`);
2116
1555
  }
2117
1556
 
2118
- const hasVisibleAssistantMessage = Array.isArray(result?.messages)
2119
- && result.messages.some((message: any) => message?.role === 'assistant' && typeof message?.content === 'string' && message.content.trim());
2120
- const shouldClampStaleGeneratingToIdle =
2121
- result?.status === 'generating'
2122
- && this.currentStatus === 'idle'
2123
- && !this.currentTurnScope
2124
- && !result?.activeModal
2125
- && hasVisibleAssistantMessage
2126
- && !hasVisibleInterruptPrompt(screenText);
2127
- if (shouldClampStaleGeneratingToIdle) {
2128
- result = {
2129
- ...result,
2130
- status: 'idle',
2131
- messages: Array.isArray(result.messages)
2132
- ? result.messages.map((message: any) => {
2133
- if (message?.role !== 'assistant' || !message?.meta?.streaming) return message;
2134
- const nextMeta = { ...(message.meta || {}) };
2135
- delete nextMeta.streaming;
2136
- return {
2137
- ...message,
2138
- ...(Object.keys(nextMeta).length > 0 ? { meta: nextMeta } : { meta: undefined }),
2139
- };
2140
- })
2141
- : result.messages,
2142
- };
2143
- }
1557
+ const activeModal = (parsed as any).activeModal ?? parsed.modal ?? null;
1558
+ const bufferState = this.getBufferState();
1559
+ const result = {
1560
+ id: (parsed as any).id || 'cli_session',
1561
+ status: parsed.status || this.currentStatus,
1562
+ title: (parsed as any).title || this.cliName,
1563
+ messages: normalizeCliParsedMessages(parsed.messages, {
1564
+ scope: null,
1565
+ lastOutputAt: this.lastOutputAt,
1566
+ }),
1567
+ activeModal,
1568
+ providerSessionId: typeof (parsed as any).providerSessionId === 'string' ? (parsed as any).providerSessionId : undefined,
1569
+ ...(bufferState ? { bufferState } : {}),
1570
+ ...((parsed as any).transcriptAuthority === 'provider' || (parsed as any).transcriptAuthority === 'daemon'
1571
+ ? { transcriptAuthority: (parsed as any).transcriptAuthority }
1572
+ : this.providerOwnsTranscript() ? { transcriptAuthority: 'provider' } : {}),
1573
+ ...((parsed as any).coverage === 'full' || (parsed as any).coverage === 'tail' || (parsed as any).coverage === 'current-turn'
1574
+ ? { coverage: (parsed as any).coverage }
1575
+ : this.providerOwnsTranscript() ? { coverage: this.shouldUseFullProviderTranscriptContext() ? 'full' : 'tail' } : {}),
1576
+ };
2144
1577
 
2145
1578
  this.parsedStatusCache = {
2146
- committedMessagesRef: this.committedMessages,
2147
1579
  responseBuffer: this.responseBuffer,
2148
1580
  currentTurnScope: this.currentTurnScope,
2149
1581
  recentOutputBuffer: this.recentOutputBuffer,
@@ -2167,7 +1599,7 @@ export class ProviderCliAdapter implements CliAdapter {
2167
1599
  accumulatedRawBuffer: this.accumulatedRawBuffer,
2168
1600
  recentOutputBuffer: this.recentOutputBuffer,
2169
1601
  terminalScreenText: this.terminalScreen.getText(),
2170
- baseMessages: this.committedMessages,
1602
+ baseMessages: [],
2171
1603
  partialResponse: this.responseBuffer,
2172
1604
  isWaitingForResponse: this.isWaitingForResponse,
2173
1605
  scope: this.currentTurnScope,
@@ -2179,46 +1611,8 @@ export class ProviderCliAdapter implements CliAdapter {
2179
1611
  }));
2180
1612
  }
2181
1613
 
2182
- private parseCurrentTranscript(baseMessages: CliChatMessage[], partialResponse: string, scope?: TurnParseScope | null, screenTextOverride?: string): any {
2183
- if (!this.cliScripts?.parseOutput) {
2184
- this.parseErrorMessage = null;
2185
- return null;
2186
- }
2187
- try {
2188
- const screenText = typeof screenTextOverride === 'string' ? screenTextOverride : this.terminalScreen.getText();
2189
- const parseBaseMessages = this.selectParseBaseMessages(baseMessages);
2190
- const input = buildCliParseInput({
2191
- accumulatedBuffer: this.accumulatedBuffer,
2192
- accumulatedRawBuffer: this.accumulatedRawBuffer,
2193
- recentOutputBuffer: this.recentOutputBuffer,
2194
- terminalScreenText: screenText,
2195
- baseMessages: parseBaseMessages,
2196
- partialResponse,
2197
- isWaitingForResponse: this.isWaitingForResponse,
2198
- scope,
2199
- runtimeSettings: this.runtimeSettings,
2200
- });
2201
- const parsed = this.cliScripts.parseOutput(input);
2202
- if (parsed && typeof parsed === 'object') {
2203
- Object.assign(parsed, validateReadChatResultPayload(parsed, `${this.cliType} parseOutput`));
2204
- }
2205
- const normalizedParsed = this.suppressStaleParsedApproval(parsed, input.recentBuffer, input.screenText);
2206
- if (normalizedParsed && Array.isArray(normalizedParsed.messages)) {
2207
- normalizedParsed.messages = this.stitchParsedMessagesWithCommittedBase(
2208
- normalizedParsed.messages,
2209
- baseMessages,
2210
- parseBaseMessages,
2211
- );
2212
- this.trimLastAssistantEcho(normalizedParsed.messages, scope?.prompt || getLastUserPromptText(baseMessages));
2213
- }
2214
- this.parseErrorMessage = null;
2215
- return normalizedParsed;
2216
- } catch (e: any) {
2217
- const message = e?.message || String(e);
2218
- this.parseErrorMessage = message;
2219
- LOG.warn('CLI', `[${this.cliType}] parseOutput error: ${message}`);
2220
- throw e;
2221
- }
1614
+ private parseCurrentTranscript(_baseMessages: CliChatMessage[], _partialResponse: string, _scope?: TurnParseScope | null, _screenTextOverride?: string): any {
1615
+ return this.runParseSession();
2222
1616
  }
2223
1617
 
2224
1618
  /** Whether this adapter has CLI scripts loaded */
@@ -2277,8 +1671,6 @@ export class ProviderCliAdapter implements CliAdapter {
2277
1671
  private commitSendUserTurn(state: SendMessageState): void {
2278
1672
  if (state.didCommitUserTurn) return;
2279
1673
  state.didCommitUserTurn = true;
2280
- this.committedMessages.push({ role: 'user', content: state.text, timestamp: Date.now() });
2281
- this.syncMessageViews();
2282
1674
  }
2283
1675
 
2284
1676
  private armResponseTimeout(): void {
@@ -2499,16 +1891,6 @@ export class ProviderCliAdapter implements CliAdapter {
2499
1891
  const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === 'string'
2500
1892
  ? String(parsedStatusBeforeSend.status)
2501
1893
  : '';
2502
- const parsedMessagesBeforeSend = Array.isArray(parsedStatusBeforeSend?.messages)
2503
- ? parsedStatusBeforeSend.messages.filter((message: any) => message && (message.role === 'user' || message.role === 'assistant'))
2504
- : [];
2505
- const shouldCommitParsedIdleBeforeSend = !allowInputDuringGeneration
2506
- && parsedSessionStatus === 'idle'
2507
- && parsedMessagesBeforeSend.length > this.committedMessages.length
2508
- && parsedMessagesBeforeSend.some((message: any) => message?.role === 'assistant' && typeof message?.content === 'string' && message.content.trim());
2509
- if (shouldCommitParsedIdleBeforeSend) {
2510
- this.commitCurrentTranscript();
2511
- }
2512
1894
  if (!allowInputDuringGeneration && (parsedSessionStatus === 'generating' || parsedSessionStatus === 'long_generating')) {
2513
1895
  throw new Error(`${this.cliName} is still processing the previous prompt`);
2514
1896
  }
@@ -2617,9 +1999,6 @@ export class ProviderCliAdapter implements CliAdapter {
2617
1999
  activeModal: this.activeModal,
2618
2000
  parseErrorMessage: this.parseErrorMessage,
2619
2001
  messageCounts: {
2620
- committed: this.committedMessages.length,
2621
- structured: this.structuredMessages.length,
2622
- visible: this.messages.length,
2623
2002
  parsedCache: Array.isArray(parsedResult?.messages) ? parsedResult.messages.length : undefined,
2624
2003
  },
2625
2004
  buffers: {
@@ -2673,7 +2052,6 @@ export class ProviderCliAdapter implements CliAdapter {
2673
2052
  responseEpoch: this.responseEpoch,
2674
2053
  resizeSuppressUntil: this.resizeSuppressUntil,
2675
2054
  lastApprovalResolvedAt: this.lastApprovalResolvedAt,
2676
- committedMessagesChangedAt: this.committedMessagesChangedAt,
2677
2055
  },
2678
2056
  finish: {
2679
2057
  idleFinishCandidate: this.idleFinishCandidate,
@@ -2807,8 +2185,6 @@ export class ProviderCliAdapter implements CliAdapter {
2807
2185
 
2808
2186
  clearHistory(): void {
2809
2187
  this.clearIdleFinishCandidate('clear_history');
2810
- this.committedMessages = [];
2811
- this.syncMessageViews();
2812
2188
  this.accumulatedBuffer = '';
2813
2189
  this.accumulatedRawBuffer = '';
2814
2190
  this.currentTurnScope = null;
@@ -2839,7 +2215,7 @@ export class ProviderCliAdapter implements CliAdapter {
2839
2215
 
2840
2216
  resolveModal(buttonIndex: number): void {
2841
2217
  let modal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
2842
- if (!modal && typeof this.cliScripts?.parseOutput === 'function') {
2218
+ if (!modal && typeof this.cliScripts?.parseSession === 'function') {
2843
2219
  try {
2844
2220
  const parsed = this.getScriptParsedStatus();
2845
2221
  const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons)
@@ -2913,10 +2289,8 @@ export class ProviderCliAdapter implements CliAdapter {
2913
2289
  startupParseGate: this.startupParseGate,
2914
2290
  spawnAt: this.spawnAt,
2915
2291
  workingDir: this.workingDir,
2916
- messages: this.messages,
2917
- committedMessages: this.committedMessages,
2918
- structuredMessages: this.structuredMessages,
2919
- messageCount: this.committedMessages.length,
2292
+ messages: [],
2293
+ messageCount: 0,
2920
2294
  screenText: screenText.slice(-4000),
2921
2295
  currentTurnScope: this.currentTurnScope,
2922
2296
  startupBuffer: this.startupBuffer.slice(-4000),
@@ -2969,7 +2343,7 @@ export class ProviderCliAdapter implements CliAdapter {
2969
2343
  lifecycleStatus: this.isWaitingForResponse ? 'awaiting_response' : 'idle',
2970
2344
  activeModal: this.activeModal,
2971
2345
  currentTurnScope: this.currentTurnScope,
2972
- messages: summarizeCliTraceMessages(this.committedMessages, 5),
2346
+ messages: [],
2973
2347
  };
2974
2348
  }
2975
2349