@adhdev/daemon-core 0.8.83 → 0.8.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,6 +27,51 @@ import { mergeProviderPatchState, resolveProviderStateSurface } from './provider
27
27
  import { normalizeProviderSessionId } from './provider-session-id.js';
28
28
  import { buildChatMessage, buildRuntimeSystemChatMessage, normalizeChatMessages } from './chat-message-normalization.js';
29
29
 
30
+ type PersistableCliHistoryMessage = {
31
+ role: string;
32
+ content: string;
33
+ kind?: string;
34
+ senderName?: string;
35
+ receivedAt?: number;
36
+ };
37
+
38
+ function normalizePersistableCliHistoryContent(content: unknown): string {
39
+ return flattenContent(content as any).replace(/\s+/g, ' ').trim();
40
+ }
41
+
42
+ function buildPersistableCliHistorySignature(message: PersistableCliHistoryMessage): string {
43
+ return [
44
+ String(message.role || ''),
45
+ String(message.kind || ''),
46
+ String(message.senderName || ''),
47
+ normalizePersistableCliHistoryContent(message.content),
48
+ ].join('|');
49
+ }
50
+
51
+ export function buildIncrementalHistoryAppendMessages(
52
+ previousMessages: PersistableCliHistoryMessage[],
53
+ currentMessages: PersistableCliHistoryMessage[],
54
+ ): PersistableCliHistoryMessage[] {
55
+ if (!Array.isArray(currentMessages) || currentMessages.length === 0) return [];
56
+ if (!Array.isArray(previousMessages) || previousMessages.length === 0) return currentMessages;
57
+
58
+ const previousSignatures = previousMessages.map(buildPersistableCliHistorySignature);
59
+ const currentSignatures = currentMessages.map(buildPersistableCliHistorySignature);
60
+
61
+ let sharedPrefixLength = 0;
62
+ while (
63
+ sharedPrefixLength < previousSignatures.length
64
+ && sharedPrefixLength < currentSignatures.length
65
+ && previousSignatures[sharedPrefixLength] === currentSignatures[sharedPrefixLength]
66
+ ) {
67
+ sharedPrefixLength += 1;
68
+ }
69
+
70
+ if (sharedPrefixLength === currentSignatures.length) return [];
71
+ if (sharedPrefixLength === previousSignatures.length) return currentMessages.slice(sharedPrefixLength);
72
+ return currentMessages;
73
+ }
74
+
30
75
  let CachedDatabaseSync: (new (path: string, options?: { readOnly?: boolean }) => {
31
76
  prepare(sql: string): { get(...params: Array<string | number>): unknown };
32
77
  close(): void;
@@ -112,6 +157,7 @@ export class CliProviderInstance implements ProviderInstance {
112
157
  private appliedEffectKeys = new Set<string>();
113
158
  private historyWriter: ChatHistoryWriter;
114
159
  private runtimeMessages: Array<{ key: string; message: ChatMessage }> = [];
160
+ private lastPersistedHistoryMessages: PersistableCliHistoryMessage[] = [];
115
161
  readonly instanceId: string;
116
162
  private suppressIdleHistoryReplay = false;
117
163
  private errorMessage: string | undefined = undefined;
@@ -200,6 +246,13 @@ export class CliProviderInstance implements ProviderInstance {
200
246
  this.providerSessionId,
201
247
  this.instanceId,
202
248
  );
249
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
250
+ role: message.role,
251
+ content: message.content,
252
+ kind: message.kind,
253
+ senderName: message.senderName,
254
+ receivedAt: message.receivedAt,
255
+ }));
203
256
  this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
204
257
  if (restoredHistory.messages.length > 0) {
205
258
  this.adapter.seedCommittedMessages(
@@ -363,15 +416,24 @@ export class CliProviderInstance implements ProviderInstance {
363
416
  messagesToSave = messagesToSave.slice(0, lastIdx);
364
417
  }
365
418
  }
366
- if (!shouldSkipReplayPersist && messagesToSave.length > 0) {
419
+ const normalizedMessagesToSave = messagesToSave.map((message: PersistableCliHistoryMessage & { timestamp?: number }) => ({
420
+ role: message.role,
421
+ content: flattenContent(message.content),
422
+ kind: typeof message.kind === 'string' ? message.kind : undefined,
423
+ senderName: typeof message.senderName === 'string' ? message.senderName : undefined,
424
+ receivedAt: typeof message.receivedAt === 'number' ? message.receivedAt : message.timestamp,
425
+ }));
426
+ if (!shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
427
+ const incrementalMessages = buildIncrementalHistoryAppendMessages(this.lastPersistedHistoryMessages, normalizedMessagesToSave);
367
428
  this.historyWriter.appendNewMessages(
368
429
  this.type,
369
- messagesToSave,
430
+ incrementalMessages,
370
431
  parsedStatus?.title || dirName,
371
432
  this.instanceId,
372
433
  this.providerSessionId,
373
434
  );
374
435
  }
436
+ this.lastPersistedHistoryMessages = normalizedMessagesToSave;
375
437
  }
376
438
 
377
439
  this.applyProviderResponse(parsedStatus, { phase: 'immediate' });
@@ -393,7 +455,9 @@ export class CliProviderInstance implements ProviderInstance {
393
455
  ? 'error'
394
456
  : autoApproveActive && parsedStatus?.status === 'waiting_approval'
395
457
  ? 'generating'
396
- : (parsedStatus?.status || visibleStatus),
458
+ : (adapterStatus.status !== 'idle'
459
+ ? visibleStatus
460
+ : (parsedStatus?.status || visibleStatus)),
397
461
  messages: mergedMessages,
398
462
  activeModal: autoApproveActive ? null : (parsedStatus?.activeModal ?? adapterStatus.activeModal),
399
463
  inputContent: '',
@@ -640,6 +704,7 @@ export class CliProviderInstance implements ProviderInstance {
640
704
 
641
705
  if (data.sessionEvent === 'new_session') {
642
706
  this.runtimeMessages = [];
707
+ this.lastPersistedHistoryMessages = [];
643
708
  this.suppressIdleHistoryReplay = false;
644
709
  this.adapter.clearHistory();
645
710
  }
@@ -3,5 +3,7 @@ export function shouldAutoRestoreHostedSessionsOnStartup(env = process.env) {
3
3
  ? env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP.trim().toLowerCase()
4
4
  : ''
5
5
 
6
+ if (!raw) return true
7
+ if (raw === '0' || raw === 'false' || raw === 'no') return false
6
8
  return raw === '1' || raw === 'true' || raw === 'yes'
7
9
  }
@@ -3,5 +3,7 @@ export function shouldAutoRestoreHostedSessionsOnStartup(env: NodeJS.ProcessEnv
3
3
  ? env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP.trim().toLowerCase()
4
4
  : ''
5
5
 
6
+ if (!raw) return true
7
+ if (raw === '0' || raw === 'false' || raw === 'no') return false
6
8
  return raw === '1' || raw === 'true' || raw === 'yes'
7
9
  }