@adhdev/daemon-core 0.9.64 → 0.9.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat/chat-signatures.d.ts +0 -4
- package/dist/chat/chat-signatures.js +0 -4
- package/dist/chat/chat-signatures.js.map +1 -1
- package/dist/chat/chat-signatures.mjs +0 -4
- package/dist/chat/chat-signatures.mjs.map +1 -1
- package/dist/chat/subscription-updates.d.ts +0 -2
- package/dist/cli-adapters/provider-cli-adapter.d.ts +2 -30
- package/dist/cli-adapters/provider-cli-parse.d.ts +1 -8
- package/dist/cli-adapters/provider-cli-shared.d.ts +8 -3
- package/dist/commands/chat-commands.d.ts +0 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +646 -1712
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +646 -1712
- package/dist/index.mjs.map +1 -1
- package/dist/shared-types.d.ts +0 -7
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/chat/chat-signatures.ts +0 -8
- package/src/chat/subscription-updates.ts +7 -46
- package/src/cli-adapters/provider-cli-adapter.d.ts +2 -10
- package/src/cli-adapters/provider-cli-adapter.ts +66 -692
- package/src/cli-adapters/provider-cli-parse.d.ts +0 -7
- package/src/cli-adapters/provider-cli-parse.ts +2 -226
- package/src/cli-adapters/provider-cli-shared.d.ts +0 -1
- package/src/cli-adapters/provider-cli-shared.ts +8 -3
- package/src/commands/chat-commands.ts +54 -366
- package/src/daemon/dev-auto-implement.ts +3 -3
- package/src/daemon/dev-server.ts +3 -3
- package/src/index.d.ts +1 -1
- package/src/index.ts +0 -1
- package/src/launch.ts +10 -3
- package/src/providers/cli-provider-instance.ts +2 -39
- package/src/shared-types.d.ts +0 -7
- package/src/shared-types.ts +0 -8
|
@@ -18,8 +18,7 @@ import { LOG, getRecentLogs } from '../logging/logger.js';
|
|
|
18
18
|
import { getRecentDebugTrace, recordDebugTrace } from '../logging/debug-trace.js';
|
|
19
19
|
import { buildChatMessageSignature } from '../chat/chat-signatures.js';
|
|
20
20
|
import type { ChatMessage } from '../types.js';
|
|
21
|
-
import type {
|
|
22
|
-
import { normalizeChatMessages } from '../providers/chat-message-normalization.js';
|
|
21
|
+
import type { SessionTransport } from '../shared-types.js';
|
|
23
22
|
|
|
24
23
|
const RECENT_SEND_WINDOW_MS = 1200;
|
|
25
24
|
export const READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25_000;
|
|
@@ -168,137 +167,16 @@ function getChatMessageSignature(message: ChatMessage | null | undefined): strin
|
|
|
168
167
|
return buildChatMessageSignature(message);
|
|
169
168
|
}
|
|
170
169
|
|
|
171
|
-
function
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
? args.lastMessageSignature
|
|
175
|
-
: '';
|
|
176
|
-
const tailLimit = Math.max(0, Number(args?.tailLimit || 0));
|
|
177
|
-
return { knownMessageCount, lastMessageSignature, tailLimit };
|
|
170
|
+
function normalizeReadChatTailLimit(args: any): number {
|
|
171
|
+
const value = Number(args?.tailLimit || 0);
|
|
172
|
+
return Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
178
173
|
}
|
|
179
174
|
|
|
180
175
|
function normalizeReadChatMessages(payload: Record<string, any>): ChatMessage[] {
|
|
181
176
|
const messages = Array.isArray(payload.messages) ? payload.messages as ChatMessage[] : [];
|
|
182
|
-
return
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
interface ReadChatReplayCollapseInfo {
|
|
186
|
-
role: string;
|
|
187
|
-
kind: string;
|
|
188
|
-
senderName: string;
|
|
189
|
-
content: string;
|
|
190
|
-
signature: string;
|
|
191
|
-
collapsible: boolean;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function normalizeReadChatReplayTextContent(content: ChatMessage['content'] | undefined): string {
|
|
195
|
-
return flattenContent(content || '').replace(/\s+/g, ' ').trim();
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function getReadChatReplayCollapseInfo(message: ChatMessage | null | undefined): ReadChatReplayCollapseInfo | null {
|
|
199
|
-
if (!message) return null;
|
|
200
|
-
const role = typeof message.role === 'string' ? message.role.trim().toLowerCase() : '';
|
|
201
|
-
const kind = typeof message.kind === 'string' ? message.kind.trim().toLowerCase() : 'standard';
|
|
202
|
-
const senderName = typeof message.senderName === 'string' ? message.senderName.trim().toLowerCase() : '';
|
|
203
|
-
const collapsible = role === 'assistant' || role === 'system';
|
|
204
|
-
if (!collapsible) return { role, kind, senderName, content: '', signature: '', collapsible };
|
|
205
|
-
const content = normalizeReadChatReplayTextContent(message.content);
|
|
206
|
-
return {
|
|
207
|
-
role,
|
|
208
|
-
kind,
|
|
209
|
-
senderName,
|
|
210
|
-
content,
|
|
211
|
-
signature: `${role}:${kind}:${senderName}:${content}`,
|
|
212
|
-
collapsible,
|
|
213
|
-
};
|
|
177
|
+
return messages;
|
|
214
178
|
}
|
|
215
179
|
|
|
216
|
-
function isStableReadChatAssistantAnswerInfo(info: ReadChatReplayCollapseInfo | null): boolean {
|
|
217
|
-
if (!info) return false;
|
|
218
|
-
if (info.role !== 'assistant') return false;
|
|
219
|
-
if (info.kind && info.kind !== 'standard') return false;
|
|
220
|
-
if (info.content.length < 160) return false;
|
|
221
|
-
|
|
222
|
-
// A provider may surface expanded command output as a standard assistant bubble
|
|
223
|
-
// (for example Claude Code's "Bash command ..." block). That is live work output,
|
|
224
|
-
// not a stable final answer. Treating it as a terminal answer would hide the
|
|
225
|
-
// real final response and violate read_chat fidelity.
|
|
226
|
-
if (/^(bash|shell|terminal) command\b/i.test(info.content)) return false;
|
|
227
|
-
return true;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
function isReplayedAssistantAnswerAfterStableAnswerInfo(
|
|
231
|
-
info: ReadChatReplayCollapseInfo | null,
|
|
232
|
-
stableContent: string,
|
|
233
|
-
): boolean {
|
|
234
|
-
if (!info || !stableContent) return false;
|
|
235
|
-
if (info.role !== 'assistant') return false;
|
|
236
|
-
if (info.kind && info.kind !== 'standard') return false;
|
|
237
|
-
const content = info.content;
|
|
238
|
-
if (content.length < 80 || stableContent.length < 80) return false;
|
|
239
|
-
return content === stableContent || content.startsWith(stableContent) || stableContent.startsWith(content);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
export function collapseReplayDuplicatesFromReadChat(messages: ChatMessage[]): ChatMessage[] {
|
|
243
|
-
const collapsed: ChatMessage[] = [];
|
|
244
|
-
const replaySignaturesInCurrentTurn = new Set<string>();
|
|
245
|
-
let stableAssistantAnswerContentInCurrentTurn = '';
|
|
246
|
-
let stableAssistantAnswerCollapsedIndex = -1;
|
|
247
|
-
let stableAssistantAnswerHadInterveningActivity = false;
|
|
248
|
-
let previousReplaySignature = '';
|
|
249
|
-
|
|
250
|
-
for (const message of messages) {
|
|
251
|
-
const info = getReadChatReplayCollapseInfo(message);
|
|
252
|
-
if (info?.role === 'user') {
|
|
253
|
-
replaySignaturesInCurrentTurn.clear();
|
|
254
|
-
stableAssistantAnswerContentInCurrentTurn = '';
|
|
255
|
-
stableAssistantAnswerCollapsedIndex = -1;
|
|
256
|
-
stableAssistantAnswerHadInterveningActivity = false;
|
|
257
|
-
previousReplaySignature = '';
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (info?.collapsible && info.signature) {
|
|
261
|
-
if (previousReplaySignature === info.signature) continue;
|
|
262
|
-
if (replaySignaturesInCurrentTurn.has(info.signature)) continue;
|
|
263
|
-
if (isReplayedAssistantAnswerAfterStableAnswerInfo(info, stableAssistantAnswerContentInCurrentTurn)) {
|
|
264
|
-
const isAdjacentFullerAssistantAnswer =
|
|
265
|
-
info.role === 'assistant'
|
|
266
|
-
&& (!info.kind || info.kind === 'standard')
|
|
267
|
-
&& stableAssistantAnswerCollapsedIndex >= 0
|
|
268
|
-
&& stableAssistantAnswerCollapsedIndex === collapsed.length - 1
|
|
269
|
-
&& !stableAssistantAnswerHadInterveningActivity
|
|
270
|
-
&& info.content.length > stableAssistantAnswerContentInCurrentTurn.length
|
|
271
|
-
&& info.content.startsWith(stableAssistantAnswerContentInCurrentTurn);
|
|
272
|
-
if (isAdjacentFullerAssistantAnswer) {
|
|
273
|
-
collapsed[stableAssistantAnswerCollapsedIndex] = message;
|
|
274
|
-
replaySignaturesInCurrentTurn.add(info.signature);
|
|
275
|
-
stableAssistantAnswerContentInCurrentTurn = info.content;
|
|
276
|
-
previousReplaySignature = info.signature;
|
|
277
|
-
}
|
|
278
|
-
continue;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
collapsed.push(message);
|
|
283
|
-
previousReplaySignature = info?.collapsible ? info.signature : '';
|
|
284
|
-
if (info?.collapsible && info.signature) {
|
|
285
|
-
replaySignaturesInCurrentTurn.add(info.signature);
|
|
286
|
-
}
|
|
287
|
-
if (isStableReadChatAssistantAnswerInfo(info)) {
|
|
288
|
-
stableAssistantAnswerContentInCurrentTurn = info?.content || '';
|
|
289
|
-
stableAssistantAnswerCollapsedIndex = collapsed.length - 1;
|
|
290
|
-
stableAssistantAnswerHadInterveningActivity = false;
|
|
291
|
-
} else if (
|
|
292
|
-
stableAssistantAnswerContentInCurrentTurn
|
|
293
|
-
&& info?.role === 'assistant'
|
|
294
|
-
&& (!info.kind || info.kind !== 'standard')
|
|
295
|
-
) {
|
|
296
|
-
stableAssistantAnswerHadInterveningActivity = true;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return collapsed;
|
|
301
|
-
}
|
|
302
180
|
|
|
303
181
|
function deriveHistoryDedupKey(message: ChatMessage & { _unitKey?: string; _turnKey?: string }): string | undefined {
|
|
304
182
|
const unitKey = typeof message._unitKey === 'string' ? message._unitKey.trim() : '';
|
|
@@ -334,153 +212,15 @@ function toHistoryPersistedMessages(messages: ChatMessage[]): Array<{
|
|
|
334
212
|
}));
|
|
335
213
|
}
|
|
336
214
|
|
|
337
|
-
function
|
|
338
|
-
if (!signature) return -1;
|
|
339
|
-
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
340
|
-
if (getChatMessageSignature(messages[index]) === signature) {
|
|
341
|
-
return index;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
return -1;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
function isReadChatConversationAnchorMessage(message: ChatMessage | null | undefined): boolean {
|
|
348
|
-
if (!message) return false;
|
|
349
|
-
const role = String(message.role || '').trim().toLowerCase();
|
|
350
|
-
if (role !== 'user' && role !== 'assistant') return false;
|
|
351
|
-
const kind = String(message.kind || 'standard').trim().toLowerCase();
|
|
352
|
-
return !kind || kind === 'standard';
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
function buildVisibleReadChatTailMessages(messages: ChatMessage[], tailLimit: number): ChatMessage[] {
|
|
356
|
-
const totalMessages = messages.length;
|
|
357
|
-
if (tailLimit <= 0 || totalMessages <= tailLimit) return messages;
|
|
358
|
-
|
|
359
|
-
const tailMessages = messages.slice(-tailLimit);
|
|
360
|
-
if (tailMessages.some(isReadChatConversationAnchorMessage)) return tailMessages;
|
|
361
|
-
|
|
362
|
-
const hiddenMessages = messages.slice(0, totalMessages - tailLimit);
|
|
363
|
-
const anchors: ChatMessage[] = [];
|
|
364
|
-
const seenRoles = new Set<string>();
|
|
365
|
-
for (let index = hiddenMessages.length - 1; index >= 0 && anchors.length < 2; index -= 1) {
|
|
366
|
-
const message = hiddenMessages[index];
|
|
367
|
-
if (!isReadChatConversationAnchorMessage(message)) continue;
|
|
368
|
-
const role = String(message.role || '').trim().toLowerCase();
|
|
369
|
-
if (seenRoles.has(role)) continue;
|
|
370
|
-
seenRoles.add(role);
|
|
371
|
-
anchors.unshift(message);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
return anchors.length > 0 ? [...anchors, ...tailMessages] : tailMessages;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
function buildBoundedTailSync(messages: ChatMessage[], cursor: Required<ReadChatCursor>): {
|
|
378
|
-
syncMode: ReadChatSyncMode;
|
|
379
|
-
replaceFrom: number;
|
|
215
|
+
function buildFullTail(messages: ChatMessage[], tailLimit: number): {
|
|
380
216
|
messages: ChatMessage[];
|
|
381
217
|
totalMessages: number;
|
|
382
|
-
lastMessageSignature: string;
|
|
383
218
|
} {
|
|
384
219
|
const totalMessages = messages.length;
|
|
385
|
-
const tailMessages =
|
|
220
|
+
const tailMessages = tailLimit > 0 ? messages.slice(-tailLimit) : messages;
|
|
386
221
|
return {
|
|
387
|
-
syncMode: 'full',
|
|
388
|
-
replaceFrom: 0,
|
|
389
222
|
messages: tailMessages,
|
|
390
223
|
totalMessages,
|
|
391
|
-
lastMessageSignature: getChatMessageSignature(messages[totalMessages - 1]),
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
function computeReadChatSync(messages: ChatMessage[], cursor: Required<ReadChatCursor>): {
|
|
396
|
-
syncMode: ReadChatSyncMode;
|
|
397
|
-
replaceFrom: number;
|
|
398
|
-
messages: ChatMessage[];
|
|
399
|
-
totalMessages: number;
|
|
400
|
-
lastMessageSignature: string;
|
|
401
|
-
} {
|
|
402
|
-
const totalMessages = messages.length;
|
|
403
|
-
const lastMessageSignature = getChatMessageSignature(messages[totalMessages - 1]);
|
|
404
|
-
const { knownMessageCount, lastMessageSignature: knownSignature } = cursor;
|
|
405
|
-
|
|
406
|
-
if (!knownMessageCount || !knownSignature) {
|
|
407
|
-
return {
|
|
408
|
-
syncMode: 'full',
|
|
409
|
-
replaceFrom: 0,
|
|
410
|
-
messages,
|
|
411
|
-
totalMessages,
|
|
412
|
-
lastMessageSignature,
|
|
413
|
-
};
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
if (knownMessageCount > totalMessages) {
|
|
417
|
-
return {
|
|
418
|
-
syncMode: 'full',
|
|
419
|
-
replaceFrom: 0,
|
|
420
|
-
messages,
|
|
421
|
-
totalMessages,
|
|
422
|
-
lastMessageSignature,
|
|
423
|
-
};
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
if (knownMessageCount === totalMessages && knownSignature === lastMessageSignature) {
|
|
427
|
-
return {
|
|
428
|
-
syncMode: 'noop',
|
|
429
|
-
replaceFrom: totalMessages,
|
|
430
|
-
messages: [],
|
|
431
|
-
totalMessages,
|
|
432
|
-
lastMessageSignature,
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
if (cursor.tailLimit > 0 && knownSignature === lastMessageSignature) {
|
|
437
|
-
const requestedTailCount = Math.min(totalMessages, cursor.tailLimit);
|
|
438
|
-
if (knownMessageCount >= requestedTailCount) {
|
|
439
|
-
return {
|
|
440
|
-
syncMode: 'noop',
|
|
441
|
-
replaceFrom: totalMessages,
|
|
442
|
-
messages: [],
|
|
443
|
-
totalMessages,
|
|
444
|
-
lastMessageSignature,
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
return buildBoundedTailSync(messages, cursor);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
if (knownMessageCount < totalMessages) {
|
|
451
|
-
const anchorSignature = getChatMessageSignature(messages[knownMessageCount - 1]);
|
|
452
|
-
if (anchorSignature === knownSignature) {
|
|
453
|
-
return {
|
|
454
|
-
syncMode: 'append',
|
|
455
|
-
replaceFrom: knownMessageCount,
|
|
456
|
-
messages: messages.slice(knownMessageCount),
|
|
457
|
-
totalMessages,
|
|
458
|
-
lastMessageSignature,
|
|
459
|
-
};
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
if (cursor.tailLimit > 0) {
|
|
463
|
-
const signatureIndex = findLastMessageIndexBySignature(messages, knownSignature);
|
|
464
|
-
if (signatureIndex >= 0) {
|
|
465
|
-
return {
|
|
466
|
-
syncMode: 'append',
|
|
467
|
-
replaceFrom: knownMessageCount,
|
|
468
|
-
messages: messages.slice(signatureIndex + 1),
|
|
469
|
-
totalMessages,
|
|
470
|
-
lastMessageSignature,
|
|
471
|
-
};
|
|
472
|
-
}
|
|
473
|
-
return buildBoundedTailSync(messages, cursor);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
const replaceFrom = Math.max(0, Math.min(knownMessageCount - 1, totalMessages));
|
|
478
|
-
return {
|
|
479
|
-
syncMode: replaceFrom === 0 ? 'full' : 'replace_tail',
|
|
480
|
-
replaceFrom,
|
|
481
|
-
messages: replaceFrom === 0 ? messages : messages.slice(replaceFrom),
|
|
482
|
-
totalMessages,
|
|
483
|
-
lastMessageSignature,
|
|
484
224
|
};
|
|
485
225
|
}
|
|
486
226
|
|
|
@@ -520,31 +260,13 @@ function buildReadChatCommandResult(payload: Record<string, any>, args: any): Co
|
|
|
520
260
|
} catch (error: any) {
|
|
521
261
|
return { success: false, error: error?.message || String(error) };
|
|
522
262
|
}
|
|
523
|
-
const messages =
|
|
524
|
-
const
|
|
525
|
-
if (!cursor.knownMessageCount && !cursor.lastMessageSignature && cursor.tailLimit > 0 && messages.length > cursor.tailLimit) {
|
|
526
|
-
const tailMessages = buildVisibleReadChatTailMessages(messages, cursor.tailLimit);
|
|
527
|
-
const lastMessageSignature = getChatMessageSignature(messages[messages.length - 1]);
|
|
528
|
-
return {
|
|
529
|
-
success: true,
|
|
530
|
-
...validatedPayload,
|
|
531
|
-
messages: tailMessages,
|
|
532
|
-
syncMode: 'full',
|
|
533
|
-
replaceFrom: 0,
|
|
534
|
-
totalMessages: messages.length,
|
|
535
|
-
lastMessageSignature,
|
|
536
|
-
...(debugReadChat ? { debugReadChat } : {}),
|
|
537
|
-
};
|
|
538
|
-
}
|
|
539
|
-
const sync = computeReadChatSync(messages, cursor);
|
|
263
|
+
const messages = normalizeReadChatMessages(validatedPayload);
|
|
264
|
+
const sync = buildFullTail(messages, normalizeReadChatTailLimit(args));
|
|
540
265
|
return {
|
|
541
266
|
success: true,
|
|
542
267
|
...validatedPayload,
|
|
543
268
|
messages: sync.messages,
|
|
544
|
-
syncMode: sync.syncMode,
|
|
545
|
-
replaceFrom: sync.replaceFrom,
|
|
546
269
|
totalMessages: sync.totalMessages,
|
|
547
|
-
lastMessageSignature: sync.lastMessageSignature,
|
|
548
270
|
...(debugReadChat ? { debugReadChat } : {}),
|
|
549
271
|
};
|
|
550
272
|
}
|
|
@@ -804,10 +526,6 @@ export async function handleGetChatDebugBundle(h: CommandHelpers, args: any): Pr
|
|
|
804
526
|
status: readResult.status,
|
|
805
527
|
title: readResult.title,
|
|
806
528
|
totalMessages: readResult.totalMessages,
|
|
807
|
-
returnedMessages: Array.isArray(readResult.messages) ? readResult.messages.length : undefined,
|
|
808
|
-
syncMode: readResult.syncMode,
|
|
809
|
-
replaceFrom: readResult.replaceFrom,
|
|
810
|
-
lastMessageSignature: readResult.lastMessageSignature,
|
|
811
529
|
providerSessionId: readResult.providerSessionId,
|
|
812
530
|
transcriptAuthority: readResult.transcriptAuthority,
|
|
813
531
|
coverage: readResult.coverage,
|
|
@@ -931,25 +649,13 @@ function toNonNegativeNumber(value: any): number {
|
|
|
931
649
|
}
|
|
932
650
|
|
|
933
651
|
function getCliVisibleTranscriptCount(adapter: any): number {
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
parsedRecord = parsed && typeof parsed === 'object' ? parsed as Record<string, any> : null;
|
|
941
|
-
} catch {
|
|
942
|
-
parsedRecord = null;
|
|
943
|
-
}
|
|
652
|
+
if (typeof adapter?.getScriptParsedStatus !== 'function') return 0;
|
|
653
|
+
try {
|
|
654
|
+
const parsed = parseMaybeJson(adapter.getScriptParsedStatus());
|
|
655
|
+
return Array.isArray(parsed?.messages) ? parsed.messages.length : 0;
|
|
656
|
+
} catch {
|
|
657
|
+
return 0;
|
|
944
658
|
}
|
|
945
|
-
const parsedMessages = Array.isArray(parsedRecord?.messages) ? parsedRecord.messages : [];
|
|
946
|
-
if (!parsedRecord) return adapterMessages.length;
|
|
947
|
-
const parsedIsProviderAuthoritative = parsedRecord.transcriptAuthority === 'provider'
|
|
948
|
-
|| parsedRecord.coverage === 'full';
|
|
949
|
-
const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative
|
|
950
|
-
&& adapterMessages.length > 0
|
|
951
|
-
&& adapterMessages.length > parsedMessages.length;
|
|
952
|
-
return shouldPreferAdapterMessages ? adapterMessages.length : parsedMessages.length;
|
|
953
659
|
}
|
|
954
660
|
|
|
955
661
|
async function getStableExtensionBaseline(h: CommandHelpers): Promise<any | null> {
|
|
@@ -1022,74 +728,56 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
1022
728
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
1023
729
|
if (adapter) {
|
|
1024
730
|
_log(`${transport} adapter: ${adapter.cliType}`);
|
|
731
|
+
if (typeof adapter.getScriptParsedStatus !== 'function') {
|
|
732
|
+
return { success: false, error: `${transport} adapter parseSession unavailable` };
|
|
733
|
+
}
|
|
1025
734
|
let parsedStatus: any = null;
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
return { success: false, error: error?.message || String(error) };
|
|
1031
|
-
}
|
|
735
|
+
try {
|
|
736
|
+
parsedStatus = parseMaybeJson(adapter.getScriptParsedStatus());
|
|
737
|
+
} catch (error: any) {
|
|
738
|
+
return { success: false, error: error?.message || String(error) };
|
|
1032
739
|
}
|
|
1033
740
|
const parsedRecord = parsedStatus && typeof parsedStatus === 'object'
|
|
1034
741
|
? parsedStatus as Record<string, any>
|
|
1035
742
|
: null;
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
const
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
&& adapterStatus.messages.length > parsedRecord.messages.length;
|
|
1045
|
-
const parsedShowsApproval = hasNonEmptyModalButtons(parsedRecord?.activeModal)
|
|
1046
|
-
&& parsedRecord?.status === 'waiting_approval';
|
|
1047
|
-
const status = parsedRecord
|
|
1048
|
-
? {
|
|
1049
|
-
...parsedRecord,
|
|
1050
|
-
messages: shouldPreferAdapterMessages ? adapterStatus.messages : parsedRecord.messages,
|
|
1051
|
-
status: parsedShowsApproval
|
|
1052
|
-
? parsedRecord.status
|
|
1053
|
-
: (adapterStatus.status !== 'idle'
|
|
1054
|
-
? adapterStatus.status
|
|
1055
|
-
: (parsedRecord.status || adapterStatus.status)),
|
|
1056
|
-
activeModal: parsedRecord.activeModal || adapterStatus.activeModal,
|
|
1057
|
-
}
|
|
1058
|
-
: adapterStatus;
|
|
1059
|
-
|
|
1060
|
-
const title = typeof parsedRecord?.title === 'string' ? parsedRecord.title : undefined;
|
|
1061
|
-
const providerSessionId = typeof parsedRecord?.providerSessionId === 'string'
|
|
743
|
+
if (!parsedRecord || !Array.isArray(parsedRecord.messages)) {
|
|
744
|
+
return { success: false, error: `${transport} parser did not return messages` };
|
|
745
|
+
}
|
|
746
|
+
const adapterStatus = typeof adapter.getStatus === 'function'
|
|
747
|
+
? adapter.getStatus()
|
|
748
|
+
: {};
|
|
749
|
+
const title = typeof parsedRecord.title === 'string' ? parsedRecord.title : undefined;
|
|
750
|
+
const providerSessionId = typeof parsedRecord.providerSessionId === 'string'
|
|
1062
751
|
? parsedRecord.providerSessionId
|
|
1063
752
|
: undefined;
|
|
1064
|
-
const transcriptAuthority = parsedRecord
|
|
753
|
+
const transcriptAuthority = parsedRecord.transcriptAuthority === 'provider' || parsedRecord.transcriptAuthority === 'daemon'
|
|
1065
754
|
? parsedRecord.transcriptAuthority
|
|
1066
755
|
: undefined;
|
|
1067
|
-
const coverage = parsedRecord
|
|
756
|
+
const coverage = parsedRecord.coverage === 'full' || parsedRecord.coverage === 'tail' || parsedRecord.coverage === 'current-turn'
|
|
1068
757
|
? parsedRecord.coverage
|
|
1069
758
|
: undefined;
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
}
|
|
759
|
+
const activeModal = parsedRecord.activeModal ?? parsedRecord.modal ?? null;
|
|
760
|
+
const returnedStatus = parsedRecord.status || 'idle';
|
|
761
|
+
LOG.debug('Command', `[read_chat] cli-like parsed provider=${adapter.cliType} target=${String(args?.targetSessionId || '')} adapterStatus=${String(adapterStatus.status || '')} parsedStatus=${String(parsedRecord.status || '')} parsedMsgCount=${parsedRecord.messages.length}`);
|
|
762
|
+
return buildReadChatCommandResult({
|
|
763
|
+
messages: parsedRecord.messages,
|
|
764
|
+
status: returnedStatus,
|
|
765
|
+
activeModal,
|
|
766
|
+
debugReadChat: {
|
|
767
|
+
provider: adapter.cliType,
|
|
768
|
+
targetSessionId: String(args?.targetSessionId || ''),
|
|
769
|
+
adapterStatus: String(adapterStatus.status || ''),
|
|
770
|
+
parsedStatus: String(parsedRecord.status || ''),
|
|
771
|
+
returnedStatus: String(returnedStatus || ''),
|
|
772
|
+
shouldPreferAdapterMessages: false,
|
|
773
|
+
parsedMsgCount: parsedRecord.messages.length,
|
|
774
|
+
returnedMsgCount: parsedRecord.messages.length,
|
|
775
|
+
},
|
|
776
|
+
...(title ? { title } : {}),
|
|
777
|
+
...(providerSessionId ? { providerSessionId } : {}),
|
|
778
|
+
...(transcriptAuthority ? { transcriptAuthority } : {}),
|
|
779
|
+
...(coverage ? { coverage } : {}),
|
|
780
|
+
}, args);
|
|
1093
781
|
}
|
|
1094
782
|
return { success: false, error: `${transport} adapter not found` };
|
|
1095
783
|
}
|
|
@@ -1098,7 +1098,7 @@ export function buildCliAutoImplPrompt(ctx: DevServerContext,
|
|
|
1098
1098
|
lines.push('');
|
|
1099
1099
|
|
|
1100
1100
|
const funcToFile: Record<string, string> = {
|
|
1101
|
-
|
|
1101
|
+
parseSession: 'parse_session.js',
|
|
1102
1102
|
detectStatus: 'detect_status.js',
|
|
1103
1103
|
parseApproval: 'parse_approval.js',
|
|
1104
1104
|
};
|
|
@@ -1200,7 +1200,7 @@ export function buildCliAutoImplPrompt(ctx: DevServerContext,
|
|
|
1200
1200
|
lines.push('');
|
|
1201
1201
|
lines.push('| Function | Input | Return |');
|
|
1202
1202
|
lines.push('|---|---|---|');
|
|
1203
|
-
lines.push('| `
|
|
1203
|
+
lines.push('| `parseSession` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |');
|
|
1204
1204
|
lines.push('| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |');
|
|
1205
1205
|
lines.push('| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |');
|
|
1206
1206
|
lines.push('');
|
|
@@ -1434,7 +1434,7 @@ export function buildCliAutoImplPrompt(ctx: DevServerContext,
|
|
|
1434
1434
|
|
|
1435
1435
|
lines.push('## Required Validation');
|
|
1436
1436
|
lines.push('1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.');
|
|
1437
|
-
lines.push('2. Confirm `
|
|
1437
|
+
lines.push('2. Confirm `parseSession` produces a stable transcript without duplicating past turns when the PTY redraws.');
|
|
1438
1438
|
lines.push('3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.');
|
|
1439
1439
|
lines.push('4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.');
|
|
1440
1440
|
lines.push('5. Confirm the Python file was actually created and executed, not just described in chat text.');
|
package/src/daemon/dev-server.ts
CHANGED
|
@@ -1367,7 +1367,7 @@ export class DevServer implements DevServerContext {
|
|
|
1367
1367
|
lines.push('');
|
|
1368
1368
|
|
|
1369
1369
|
const funcToFile: Record<string, string> = {
|
|
1370
|
-
|
|
1370
|
+
parseSession: 'parse_session.js',
|
|
1371
1371
|
detectStatus: 'detect_status.js',
|
|
1372
1372
|
parseApproval: 'parse_approval.js',
|
|
1373
1373
|
};
|
|
@@ -1469,7 +1469,7 @@ export class DevServer implements DevServerContext {
|
|
|
1469
1469
|
lines.push('');
|
|
1470
1470
|
lines.push('| Function | Input | Return |');
|
|
1471
1471
|
lines.push('|---|---|---|');
|
|
1472
|
-
lines.push('| `
|
|
1472
|
+
lines.push('| `parseSession` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |');
|
|
1473
1473
|
lines.push('| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |');
|
|
1474
1474
|
lines.push('| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |');
|
|
1475
1475
|
lines.push('');
|
|
@@ -1568,7 +1568,7 @@ export class DevServer implements DevServerContext {
|
|
|
1568
1568
|
|
|
1569
1569
|
lines.push('## Required Validation');
|
|
1570
1570
|
lines.push('1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.');
|
|
1571
|
-
lines.push('2. Confirm `
|
|
1571
|
+
lines.push('2. Confirm `parseSession` produces a stable transcript without duplicating past turns when the PTY redraws.');
|
|
1572
1572
|
lines.push('3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.');
|
|
1573
1573
|
lines.push('4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.');
|
|
1574
1574
|
lines.push('5. Confirm the Python file was actually created and executed, not just described in chat text.');
|
package/src/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Core logic for daemon: CDP, Provider, IDE detection, CLI/ACP adapters and more.
|
|
5
5
|
*/
|
|
6
6
|
export type { ChatBubbleState, ChatMessage, ExtensionInfo, CommandResult as CoreCommandResult, ProviderConfig, DaemonEvent, StatusResponse, SystemInfo, DetectedIde, ProviderInfo, AgentEntry, } from './types.js';
|
|
7
|
-
export type { SessionEntry, CompactSessionEntry, CompactDaemonEntry, SessionTransport, SessionKind, SessionCapability, AgentSessionStream, ReadChatCursor,
|
|
7
|
+
export type { SessionEntry, CompactSessionEntry, CompactDaemonEntry, SessionTransport, SessionKind, SessionCapability, AgentSessionStream, ReadChatCursor, ReadChatSyncResult, TransportTopic, SessionChatTailSubscriptionParams, SessionRuntimeOutputSubscriptionParams, MachineRuntimeSubscriptionParams, SessionHostDiagnosticsSubscriptionParams, SessionModalSubscriptionParams, DaemonMetadataSubscriptionParams, SessionChatTailUpdate, SessionRuntimeOutputUpdate, MachineRuntimeUpdate, SessionHostDiagnosticsUpdate, SessionModalUpdate, DaemonMetadataUpdate, TopicUpdateEnvelope, SubscribeRequest, UnsubscribeRequest, StandaloneWsStatusPayload, AvailableProviderInfo, AcpConfigOption, AcpMode, ProviderControlSchema, StatusReportPayload, MachineInfo, SessionHostDiagnosticsSnapshot, SessionHostRecord, SessionHostWriteOwner, SessionHostAttachedClient, SessionHostLogEntry, SessionHostRequestTrace, SessionHostRuntimeTransition, DetectedIdeInfo, WorkspaceEntry, ProviderSummaryItem, ProviderSummaryMetadata, ProviderState, ProviderStatus, ProviderErrorReason, ActiveChatData, IdeProviderState, CliProviderState, AcpProviderState, ExtensionProviderState, } from './shared-types.js';
|
|
8
8
|
import type { RuntimeWriteOwner as _RuntimeWriteOwner } from './shared-types-extra.js';
|
|
9
9
|
import type { RuntimeAttachedClient as _RuntimeAttachedClient } from './shared-types-extra.js';
|
|
10
10
|
import type { RecentLaunchEntry as _RecentLaunchEntry } from './shared-types.js';
|
package/src/index.ts
CHANGED
package/src/launch.ts
CHANGED
|
@@ -433,12 +433,19 @@ export async function launchWithCdp(options: LaunchOptions = {}): Promise<Launch
|
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
+
if (!cdpReady) {
|
|
437
|
+
return {
|
|
438
|
+
success: false, ideId: targetIde.id, ideName: targetIde.displayName,
|
|
439
|
+
port, action: 'failed',
|
|
440
|
+
message: '',
|
|
441
|
+
error: `${targetIde.displayName} launched but CDP did not become available on port ${port}`,
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
436
445
|
return {
|
|
437
446
|
success: true, ideId: targetIde.id, ideName: targetIde.displayName,
|
|
438
447
|
port, action: alreadyRunning ? 'restarted' : 'started',
|
|
439
|
-
message:
|
|
440
|
-
? `${targetIde.displayName} launched with CDP on port ${port}`
|
|
441
|
-
: `${targetIde.displayName} launched (CDP may take a moment to initialize)`,
|
|
448
|
+
message: `${targetIde.displayName} launched with CDP on port ${port}`,
|
|
442
449
|
};
|
|
443
450
|
} catch (e: any) {
|
|
444
451
|
return {
|