@adhdev/daemon-core 0.9.82-rc.100 → 0.9.82-rc.102

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.9.82-rc.100",
3
+ "version": "0.9.82-rc.102",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1372,6 +1372,11 @@ export class ProviderCliAdapter implements CliAdapter {
1372
1372
  this.idleTimeout = setTimeout(() => {
1373
1373
  if (this.isWaitingForResponse && !this.hasActionableApproval()) {
1374
1374
  if (this.shouldDeferIdleTimeoutFinish()) return;
1375
+ const parsed = this.runParseSession();
1376
+ if (this.shouldKeepCodexTurnOpenForFinish(parsed)) {
1377
+ this.rescheduleCodexFinishCheck('codex_idle_timeout_not_final');
1378
+ return;
1379
+ }
1375
1380
  this.clearIdleFinishCandidate('idle_timeout_finish');
1376
1381
  this.finishResponse();
1377
1382
  }
@@ -1381,6 +1386,11 @@ export class ProviderCliAdapter implements CliAdapter {
1381
1386
  private finishResponse(): void {
1382
1387
  if (this.submitPendingUntil > Date.now()) return;
1383
1388
  if (this.responseSettleIgnoreUntil > Date.now()) return;
1389
+ const parsedBeforeFinish = this.runParseSession();
1390
+ if (this.shouldKeepCodexTurnOpenForFinish(parsedBeforeFinish)) {
1391
+ this.rescheduleCodexFinishCheck('codex_finish_not_final');
1392
+ return;
1393
+ }
1384
1394
  this.clearIdleFinishCandidate('finish_response_enter');
1385
1395
  this.recordTrace('finish_response', {
1386
1396
  ...buildCliTraceParseSnapshot({
@@ -1618,6 +1628,49 @@ export class ProviderCliAdapter implements CliAdapter {
1618
1628
  return !!lastAssistant;
1619
1629
  }
1620
1630
 
1631
+ private parsedStatusHasFinalStandardAssistantMessage(parsed: any): boolean {
1632
+ const messages = Array.isArray(parsed?.messages) ? parsed.messages : [];
1633
+ const lastAssistant = [...messages].reverse().find((message: any) => {
1634
+ if (!message || message.role !== 'assistant') return false;
1635
+ return typeof message.content === 'string' && message.content.trim().length > 0;
1636
+ });
1637
+ if (!lastAssistant) return false;
1638
+ const kind = typeof lastAssistant.kind === 'string' && lastAssistant.kind.trim()
1639
+ ? lastAssistant.kind.trim()
1640
+ : 'standard';
1641
+ return kind === 'standard' && lastAssistant.meta?.streaming !== true;
1642
+ }
1643
+
1644
+ private shouldKeepCodexTurnOpenForFinish(parsed: any): boolean {
1645
+ if (this.cliType !== 'codex-cli') return false;
1646
+ if (!this.isWaitingForResponse || !this.currentTurnScope || this.hasActionableApproval()) return false;
1647
+ const parsedStatus = typeof parsed?.status === 'string' ? parsed.status.trim() : '';
1648
+ if (parsedStatus !== 'idle') return true;
1649
+ if (parsed?.activeModal || parsed?.modal) return true;
1650
+ return !this.parsedStatusHasFinalStandardAssistantMessage(parsed);
1651
+ }
1652
+
1653
+ private rescheduleCodexFinishCheck(reason: string): void {
1654
+ this.clearIdleFinishCandidate(reason);
1655
+ this.setStatus('generating', reason);
1656
+ if (this.idleTimeout) clearTimeout(this.idleTimeout);
1657
+ this.idleTimeout = setTimeout(() => {
1658
+ if (!this.isWaitingForResponse || this.hasActionableApproval()) return;
1659
+ this.settledBuffer = this.recentOutputBuffer;
1660
+ this.evaluateSettled();
1661
+ }, this.getIdleFinishConfirmMs());
1662
+ this.recordTrace('codex_finish_deferred', {
1663
+ reason,
1664
+ ...buildCliTraceParseSnapshot({
1665
+ accumulatedBuffer: this.accumulatedBuffer,
1666
+ accumulatedRawBuffer: this.accumulatedRawBuffer,
1667
+ responseBuffer: this.responseBuffer,
1668
+ partialResponse: this.responseBuffer,
1669
+ scope: this.currentTurnScope,
1670
+ }),
1671
+ });
1672
+ }
1673
+
1621
1674
  private projectEffectiveStatus(startupModal: { message: string; buttons: string[] } | null = null): CliSessionStatus['status'] {
1622
1675
  if (this.parseErrorMessage) return 'error';
1623
1676
  if (this.hasActionableApproval(startupModal)) return 'waiting_approval';
@@ -1726,6 +1779,12 @@ export class ProviderCliAdapter implements CliAdapter {
1726
1779
  }),
1727
1780
  activeModal,
1728
1781
  providerSessionId: typeof (parsed as any).providerSessionId === 'string' ? (parsed as any).providerSessionId : undefined,
1782
+ errorMessage: typeof (parsed as any).errorMessage === 'string' && (parsed as any).errorMessage.trim()
1783
+ ? (parsed as any).errorMessage.trim()
1784
+ : undefined,
1785
+ errorReason: typeof (parsed as any).errorReason === 'string' && (parsed as any).errorReason.trim()
1786
+ ? (parsed as any).errorReason.trim()
1787
+ : undefined,
1729
1788
  ...(bufferState ? { bufferState } : {}),
1730
1789
  ...((parsed as any).transcriptAuthority === 'provider' || (parsed as any).transcriptAuthority === 'daemon'
1731
1790
  ? { transcriptAuthority: (parsed as any).transcriptAuthority }
@@ -2596,6 +2655,9 @@ export class ProviderCliAdapter implements CliAdapter {
2596
2655
  const parsedDebugState = this.getParsedDebugState();
2597
2656
  const parsedMessages = Array.isArray(parsedDebugState?.messages) ? parsedDebugState.messages : [];
2598
2657
  let effectiveStatus = this.projectEffectiveStatus(startupModal);
2658
+ if (parsedDebugState?.status === 'error') {
2659
+ effectiveStatus = 'error';
2660
+ }
2599
2661
  if (startupDetectedStatus === 'waiting_approval') {
2600
2662
  effectiveStatus = 'waiting_approval';
2601
2663
  }
@@ -2627,6 +2689,8 @@ export class ProviderCliAdapter implements CliAdapter {
2627
2689
  providerSessionId: parsedDebugState.providerSessionId,
2628
2690
  transcriptAuthority: parsedDebugState.transcriptAuthority,
2629
2691
  coverage: parsedDebugState.coverage,
2692
+ errorMessage: parsedDebugState.errorMessage,
2693
+ errorReason: parsedDebugState.errorReason,
2630
2694
  activeModal: parsedDebugState.activeModal,
2631
2695
  messageCount: parsedMessages.length,
2632
2696
  } : null,
@@ -336,6 +336,9 @@ function buildCliMessageSourceProvenance(args: {
336
336
  nativeSource?: string;
337
337
  sourcePath?: string;
338
338
  sourceMtimeMs?: number;
339
+ nativeHistoryCoverage?: string;
340
+ partialReason?: string;
341
+ unavailableReason?: string;
339
342
  nativeMessages?: ChatMessage[];
340
343
  ptyMessages?: ChatMessage[];
341
344
  returnedMessages?: ChatMessage[];
@@ -357,6 +360,9 @@ function buildCliMessageSourceProvenance(args: {
357
360
  ...(args.fallbackReason ? { fallbackReason: args.fallbackReason } : {}),
358
361
  ...(args.nativeSource ? { nativeSource: args.nativeSource } : {}),
359
362
  ...(args.sourcePath ? { sourcePath: args.sourcePath } : {}),
363
+ ...(args.nativeHistoryCoverage ? { nativeHistoryCoverage: args.nativeHistoryCoverage } : {}),
364
+ ...(args.partialReason ? { partialReason: args.partialReason } : {}),
365
+ ...(args.unavailableReason ? { unavailableReason: args.unavailableReason } : {}),
360
366
  ptyStatusApprovalOnly: args.ptyStatusApprovalOnly === true,
361
367
  staleness: {
362
368
  sourceMtimeMs: sourceMtimeMs || undefined,
@@ -378,12 +384,15 @@ function buildNativeHistoryFallbackReason(args: {
378
384
  providerType: string;
379
385
  provider?: ProviderModule;
380
386
  nativeSource?: string;
387
+ nativeHistoryCoverage?: string;
381
388
  nativeMessageCount: number;
382
389
  safeMapping: boolean;
383
390
  freshEnough: boolean;
384
391
  }): string {
385
392
  if (!supportsCliNativeTranscript(args.providerType, args.provider)) return 'provider_native_transcript_not_supported';
386
393
  if (args.nativeSource === 'native-unavailable') return 'native_history_unavailable';
394
+ if (args.nativeHistoryCoverage === 'partial') return 'native_history_partial';
395
+ if (args.nativeHistoryCoverage === 'unavailable') return 'native_history_unavailable';
387
396
  if (args.nativeSource && args.nativeSource !== 'provider-native') return `native_history_source_${args.nativeSource}`;
388
397
  if (args.nativeMessageCount <= 0) return 'native_history_empty';
389
398
  if (!args.safeMapping) return 'native_history_not_safely_mapped';
@@ -1291,6 +1300,15 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1291
1300
  const historyProviderSessionId = typeof (nativeHistory as any)?.providerSessionId === 'string'
1292
1301
  ? (nativeHistory as any).providerSessionId
1293
1302
  : readHistorySessionIdFromMessages(nativeMessages) || nativeHistorySessionId || historySessionId;
1303
+ const nativeHistoryCoverage = typeof (nativeHistory as any)?.nativeHistoryCoverage === 'string'
1304
+ ? (nativeHistory as any).nativeHistoryCoverage
1305
+ : undefined;
1306
+ const partialReason = typeof (nativeHistory as any)?.partialReason === 'string'
1307
+ ? (nativeHistory as any).partialReason
1308
+ : undefined;
1309
+ const unavailableReason = typeof (nativeHistory as any)?.unavailableReason === 'string'
1310
+ ? (nativeHistory as any).unavailableReason
1311
+ : undefined;
1294
1312
  const lookup = (nativeHistory as any).lookup === 'workspace' ? 'workspace' : 'session';
1295
1313
  const safeMapping = hasSafeNativeHistoryMapping({
1296
1314
  historySessionId: lookup === 'workspace' ? undefined : nativeHistorySessionId,
@@ -1305,7 +1323,7 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1305
1323
  nativeMessages,
1306
1324
  ptyMessages: returnedMessages,
1307
1325
  });
1308
- if ((nativeHistory as any).source === 'provider-native' && nativeMessages.length > 0 && safeMapping && freshEnough) {
1326
+ if ((nativeHistory as any).source === 'provider-native' && nativeMessages.length > 0 && nativeHistoryCoverage !== 'partial' && nativeHistoryCoverage !== 'unavailable' && safeMapping && freshEnough) {
1309
1327
  selectedMessages = finalizeStreamingMessagesWhenIdle(nativeMessages, returnedStatus);
1310
1328
  selectedProviderSessionId = historyProviderSessionId || providerSessionId;
1311
1329
  selectedTranscriptAuthority = 'provider';
@@ -1317,6 +1335,9 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1317
1335
  nativeSource: (nativeHistory as any).source,
1318
1336
  sourcePath: (nativeHistory as any).sourcePath,
1319
1337
  sourceMtimeMs: (nativeHistory as any).sourceMtimeMs,
1338
+ nativeHistoryCoverage,
1339
+ partialReason,
1340
+ unavailableReason,
1320
1341
  nativeMessages,
1321
1342
  ptyMessages: returnedMessages,
1322
1343
  returnedMessages: selectedMessages,
@@ -1329,6 +1350,7 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1329
1350
  providerType,
1330
1351
  provider,
1331
1352
  nativeSource: (nativeHistory as any).source,
1353
+ nativeHistoryCoverage,
1332
1354
  nativeMessageCount: nativeMessages.length,
1333
1355
  safeMapping,
1334
1356
  freshEnough,
@@ -1341,6 +1363,9 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1341
1363
  nativeSource: (nativeHistory as any).source,
1342
1364
  sourcePath: (nativeHistory as any).sourcePath,
1343
1365
  sourceMtimeMs: (nativeHistory as any).sourceMtimeMs,
1366
+ nativeHistoryCoverage,
1367
+ partialReason,
1368
+ unavailableReason,
1344
1369
  nativeMessages,
1345
1370
  ptyMessages: returnedMessages,
1346
1371
  returnedMessages,
@@ -1425,6 +1450,15 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1425
1450
  const historyProviderSessionId = typeof (history as any)?.providerSessionId === 'string'
1426
1451
  ? (history as any).providerSessionId
1427
1452
  : readHistorySessionIdFromMessages(historyMessages) || historySessionId;
1453
+ const nativeHistoryCoverage = typeof (history as any)?.nativeHistoryCoverage === 'string'
1454
+ ? (history as any).nativeHistoryCoverage
1455
+ : undefined;
1456
+ const partialReason = typeof (history as any)?.partialReason === 'string'
1457
+ ? (history as any).partialReason
1458
+ : undefined;
1459
+ const unavailableReason = typeof (history as any)?.unavailableReason === 'string'
1460
+ ? (history as any).unavailableReason
1461
+ : undefined;
1428
1462
  const safeMapping = supportsCliNativeTranscript(agentStr, provider)
1429
1463
  ? hasSafeNativeHistoryMapping({
1430
1464
  historySessionId: lookup === 'workspace' ? undefined : historySessionId,
@@ -1436,6 +1470,8 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1436
1470
  const nativeSelected = supportsCliNativeTranscript(agentStr, provider)
1437
1471
  && (history as any).source === 'provider-native'
1438
1472
  && historyMessages.length > 0
1473
+ && nativeHistoryCoverage !== 'partial'
1474
+ && nativeHistoryCoverage !== 'unavailable'
1439
1475
  && safeMapping;
1440
1476
  const messageSource = buildCliMessageSourceProvenance({
1441
1477
  selected: nativeSelected ? 'native-history' : 'pty-parser',
@@ -1447,6 +1483,7 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1447
1483
  providerType: agentStr,
1448
1484
  provider,
1449
1485
  nativeSource: (history as any).source,
1486
+ nativeHistoryCoverage,
1450
1487
  nativeMessageCount: historyMessages.length,
1451
1488
  safeMapping,
1452
1489
  freshEnough: true,
@@ -1454,6 +1491,9 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
1454
1491
  nativeSource: (history as any).source,
1455
1492
  sourcePath: (history as any).sourcePath,
1456
1493
  sourceMtimeMs: (history as any).sourceMtimeMs,
1494
+ nativeHistoryCoverage,
1495
+ partialReason,
1496
+ unavailableReason,
1457
1497
  nativeMessages: historyMessages,
1458
1498
  returnedMessages: historyMessages,
1459
1499
  safeMapping,
@@ -1345,7 +1345,15 @@ function rewriteCanonicalSavedHistory(agentType: string, historySessionId: strin
1345
1345
 
1346
1346
  export type ProviderNativeHistoryScripts = Record<string, ((input: any) => any) | undefined>;
1347
1347
 
1348
- type ProviderNativeHistoryReadResult = { records: HistoryMessage[]; sourcePath: string; sourceMtimeMs: number };
1348
+ type ProviderNativeHistoryReadResult = {
1349
+ records: HistoryMessage[];
1350
+ sourcePath: string;
1351
+ sourceMtimeMs: number;
1352
+ providerSessionId?: string;
1353
+ nativeHistoryCoverage?: string;
1354
+ partialReason?: string;
1355
+ unavailableReason?: string;
1356
+ };
1349
1357
 
1350
1358
  function getNativeHistoryScriptName(canonicalHistory: ProviderCanonicalHistoryConfig | undefined, key: 'readSession' | 'listSessions'): string {
1351
1359
  const configured = canonicalHistory?.scripts?.[key];
@@ -1409,6 +1417,10 @@ function callProviderNativeHistoryRead(
1409
1417
  records,
1410
1418
  sourcePath: typeof (result as any).sourcePath === 'string' ? (result as any).sourcePath : '',
1411
1419
  sourceMtimeMs: Number((result as any).sourceMtimeMs) || 0,
1420
+ providerSessionId: typeof (result as any).providerSessionId === 'string' ? (result as any).providerSessionId.trim() : undefined,
1421
+ nativeHistoryCoverage: typeof (result as any).nativeHistoryCoverage === 'string' ? (result as any).nativeHistoryCoverage.trim() : undefined,
1422
+ partialReason: typeof (result as any).partialReason === 'string' ? (result as any).partialReason.trim() : undefined,
1423
+ unavailableReason: typeof (result as any).unavailableReason === 'string' ? (result as any).unavailableReason.trim() : undefined,
1412
1424
  };
1413
1425
  }
1414
1426
 
@@ -1479,7 +1491,17 @@ export function readProviderChatHistory(
1479
1491
  historyBehavior?: ProviderHistoryBehavior;
1480
1492
  scripts?: ProviderNativeHistoryScripts;
1481
1493
  } = {},
1482
- ): { messages: HistoryMessage[]; hasMore: boolean; source: 'provider-native' | 'adhdev-mirror' | 'native-unavailable'; sourcePath?: string; sourceMtimeMs?: number } {
1494
+ ): {
1495
+ messages: HistoryMessage[];
1496
+ hasMore: boolean;
1497
+ source: 'provider-native' | 'adhdev-mirror' | 'native-unavailable';
1498
+ sourcePath?: string;
1499
+ sourceMtimeMs?: number;
1500
+ providerSessionId?: string;
1501
+ nativeHistoryCoverage?: string;
1502
+ partialReason?: string;
1503
+ unavailableReason?: string;
1504
+ } {
1483
1505
  if (isNativeSourceCanonicalHistory(options.canonicalHistory) && (options.historySessionId || options.workspace)) {
1484
1506
  const nativeResult = buildNativeHistoryReadResult(agentType, options.canonicalHistory, options.scripts, options.historySessionId, options.workspace);
1485
1507
  if (!nativeResult) return { messages: [], hasMore: false, source: 'native-unavailable' };
@@ -1488,6 +1510,10 @@ export function readProviderChatHistory(
1488
1510
  source: 'provider-native',
1489
1511
  sourcePath: nativeResult.sourcePath,
1490
1512
  sourceMtimeMs: nativeResult.sourceMtimeMs,
1513
+ providerSessionId: nativeResult.providerSessionId,
1514
+ nativeHistoryCoverage: nativeResult.nativeHistoryCoverage,
1515
+ partialReason: nativeResult.partialReason,
1516
+ unavailableReason: nativeResult.unavailableReason,
1491
1517
  };
1492
1518
  }
1493
1519
  return {
@@ -497,8 +497,14 @@ export class CliProviderInstance implements ProviderInstance {
497
497
  if (typeof this.adapter.getScriptParsedStatus === 'function') {
498
498
  try {
499
499
  parsedStatus = this.adapter.getScriptParsedStatus() || null;
500
- this.errorMessage = undefined;
501
- this.errorReason = undefined;
500
+ const parsedErrorMessage = typeof parsedStatus?.errorMessage === 'string' && parsedStatus.errorMessage.trim()
501
+ ? parsedStatus.errorMessage.trim()
502
+ : undefined;
503
+ const parsedErrorReason = typeof parsedStatus?.errorReason === 'string' && parsedStatus.errorReason.trim()
504
+ ? parsedStatus.errorReason.trim() as ProviderErrorReason
505
+ : undefined;
506
+ this.errorMessage = parsedErrorMessage;
507
+ this.errorReason = parsedErrorReason;
502
508
  } catch (error: any) {
503
509
  parseErrorMessage = error?.message || String(error);
504
510
  this.errorMessage = parseErrorMessage;
@@ -509,7 +515,7 @@ export class CliProviderInstance implements ProviderInstance {
509
515
  this.errorReason = undefined;
510
516
  }
511
517
  const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, Date.now());
512
- const visibleStatus = parseErrorMessage
518
+ const visibleStatus = parseErrorMessage || parsedStatus?.status === 'error'
513
519
  ? 'error'
514
520
  : (autoApproveActive ? 'generating' : adapterStatus.status);
515
521
  const parsedProviderSessionId = normalizeProviderSessionId(