@adhdev/daemon-core 0.8.94 → 0.8.95

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.
@@ -48,6 +48,7 @@ export declare class CliProviderInstance implements ProviderInstance {
48
48
  private historyWriter;
49
49
  private runtimeMessages;
50
50
  private lastPersistedHistoryMessages;
51
+ private lastCanonicalHermesSyncMtimeMs;
51
52
  readonly instanceId: string;
52
53
  private suppressIdleHistoryReplay;
53
54
  private errorMessage;
@@ -104,6 +105,8 @@ export declare class CliProviderInstance implements ProviderInstance {
104
105
  private mergeConversationMessages;
105
106
  private formatApprovalRequestMessage;
106
107
  private promoteProviderSessionId;
108
+ private syncCanonicalHermesSavedHistoryIfNeeded;
109
+ private restorePersistedHistoryFromCurrentSession;
107
110
  private getProbeDirectories;
108
111
  private buildSqlPlaceholderList;
109
112
  private querySqliteText;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/session-host-core",
3
- "version": "0.8.94",
3
+ "version": "0.8.95",
4
4
  "description": "ADHDev local session host core \u2014 session registry, protocol, buffers",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.8.94",
3
+ "version": "0.8.95",
4
4
  "description": "ADHDev daemon core \u2014 CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -17,7 +17,7 @@ import { ProviderCliAdapter } from '../cli-adapters/provider-cli-adapter.js';
17
17
  import type { CliProviderModule } from '../cli-adapters/provider-cli-adapter.js';
18
18
  import type { PtyRuntimeMetadata, PtyTransportFactory } from '../cli-adapters/pty-transport.js';
19
19
  import { StatusMonitor } from './status-monitor.js';
20
- import { ChatHistoryWriter, readChatHistory } from '../config/chat-history.js';
20
+ import { ChatHistoryWriter, readChatHistory, rebuildHermesSavedHistoryFromCanonicalSession } from '../config/chat-history.js';
21
21
  import { LOG } from '../logging/logger.js';
22
22
  import type { ChatMessage } from '../types.js';
23
23
  import { buildPersistedProviderEffectMessage, normalizeProviderEffects } from './control-effects.js';
@@ -158,6 +158,7 @@ export class CliProviderInstance implements ProviderInstance {
158
158
  private historyWriter: ChatHistoryWriter;
159
159
  private runtimeMessages: Array<{ key: string; message: ChatMessage }> = [];
160
160
  private lastPersistedHistoryMessages: PersistableCliHistoryMessage[] = [];
161
+ private lastCanonicalHermesSyncMtimeMs = 0;
161
162
  readonly instanceId: string;
162
163
  private suppressIdleHistoryReplay = false;
163
164
  private errorMessage: string | undefined = undefined;
@@ -238,34 +239,7 @@ export class CliProviderInstance implements ProviderInstance {
238
239
  await this.enforceFreshSessionLaunchIfNeeded();
239
240
  this.maybeAppendRuntimeRecoveryMessage(this.adapter.getRuntimeMetadata());
240
241
  if (this.providerSessionId) {
241
- this.historyWriter.compactHistorySession(this.type, this.providerSessionId);
242
- const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
243
- this.historyWriter.seedSessionHistory(
244
- this.type,
245
- restoredHistory.messages,
246
- this.providerSessionId,
247
- this.instanceId,
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
- }));
256
- this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
257
- if (restoredHistory.messages.length > 0) {
258
- this.adapter.seedCommittedMessages(
259
- restoredHistory.messages.map((message) => ({
260
- role: message.role,
261
- content: message.content,
262
- timestamp: message.receivedAt,
263
- receivedAt: message.receivedAt,
264
- kind: message.kind,
265
- senderName: message.senderName,
266
- })),
267
- );
268
- }
242
+ this.restorePersistedHistoryFromCurrentSession();
269
243
  }
270
244
  if (this.providerSessionId && this.launchMode === 'resume') {
271
245
  const resumedAt = Date.now();
@@ -401,6 +375,7 @@ export class CliProviderInstance implements ProviderInstance {
401
375
  : [];
402
376
  }
403
377
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
378
+ const canonicalHermesBackedHistory = this.syncCanonicalHermesSavedHistoryIfNeeded();
404
379
 
405
380
  const dirName = this.workingDir.split('/').filter(Boolean).pop() || 'session';
406
381
 
@@ -423,7 +398,7 @@ export class CliProviderInstance implements ProviderInstance {
423
398
  senderName: typeof message.senderName === 'string' ? message.senderName : undefined,
424
399
  receivedAt: typeof message.receivedAt === 'number' ? message.receivedAt : message.timestamp,
425
400
  }));
426
- if (!shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
401
+ if (!canonicalHermesBackedHistory && !shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
427
402
  const incrementalMessages = buildIncrementalHistoryAppendMessages(this.lastPersistedHistoryMessages, normalizedMessagesToSave);
428
403
  this.historyWriter.appendNewMessages(
429
404
  this.type,
@@ -433,7 +408,9 @@ export class CliProviderInstance implements ProviderInstance {
433
408
  this.providerSessionId,
434
409
  );
435
410
  }
436
- this.lastPersistedHistoryMessages = normalizedMessagesToSave;
411
+ if (!canonicalHermesBackedHistory) {
412
+ this.lastPersistedHistoryMessages = normalizedMessagesToSave;
413
+ }
437
414
  }
438
415
 
439
416
  this.applyProviderResponse(parsedStatus, { phase: 'immediate' });
@@ -949,6 +926,7 @@ export class CliProviderInstance implements ProviderInstance {
949
926
  this.providerSessionId = nextSessionId;
950
927
  this.historyWriter.promoteHistorySession(this.type, previousHistorySessionId, nextSessionId);
951
928
  this.historyWriter.writeSessionStart(this.type, nextSessionId, this.workingDir, this.instanceId);
929
+ this.restorePersistedHistoryFromCurrentSession();
952
930
  this.adapter.updateRuntimeMeta({ providerSessionId: nextSessionId });
953
931
  this.onProviderSessionResolved?.({
954
932
  instanceId: this.instanceId,
@@ -961,6 +939,63 @@ export class CliProviderInstance implements ProviderInstance {
961
939
  LOG.info('CLI', `[${this.type}] discovered provider session id: ${nextSessionId}`);
962
940
  }
963
941
 
942
+ private syncCanonicalHermesSavedHistoryIfNeeded(): boolean {
943
+ if (this.type !== 'hermes-cli' || !this.providerSessionId) return false;
944
+ try {
945
+ const canonicalPath = path.join(os.homedir(), '.hermes', 'sessions', `session_${this.providerSessionId}.json`);
946
+ if (!fs.existsSync(canonicalPath)) return false;
947
+ const stat = fs.statSync(canonicalPath);
948
+ if (stat.mtimeMs <= this.lastCanonicalHermesSyncMtimeMs) return true;
949
+ const rebuilt = rebuildHermesSavedHistoryFromCanonicalSession(this.providerSessionId);
950
+ if (!rebuilt) return false;
951
+ this.lastCanonicalHermesSyncMtimeMs = stat.mtimeMs;
952
+ const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
953
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
954
+ role: message.role,
955
+ content: message.content,
956
+ kind: message.kind,
957
+ senderName: message.senderName,
958
+ receivedAt: message.receivedAt,
959
+ }));
960
+ return true;
961
+ } catch {
962
+ return false;
963
+ }
964
+ }
965
+
966
+ private restorePersistedHistoryFromCurrentSession(): void {
967
+ if (!this.providerSessionId) return;
968
+ this.syncCanonicalHermesSavedHistoryIfNeeded();
969
+ this.historyWriter.compactHistorySession(this.type, this.providerSessionId);
970
+ const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
971
+ this.historyWriter.seedSessionHistory(
972
+ this.type,
973
+ restoredHistory.messages,
974
+ this.providerSessionId,
975
+ this.instanceId,
976
+ );
977
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
978
+ role: message.role,
979
+ content: message.content,
980
+ kind: message.kind,
981
+ senderName: message.senderName,
982
+ receivedAt: message.receivedAt,
983
+ }));
984
+ this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
985
+ if (restoredHistory.messages.length > 0) {
986
+ this.adapter.seedCommittedMessages(
987
+ restoredHistory.messages.map((message) => ({
988
+ role: message.role,
989
+ content: message.content,
990
+ timestamp: message.receivedAt,
991
+ receivedAt: message.receivedAt,
992
+ kind: message.kind,
993
+ senderName: message.senderName,
994
+ })),
995
+ );
996
+ }
997
+ }
998
+
964
999
 
965
1000
  private getProbeDirectories(): string[] {
966
1001
  const dirs = new Set<string>();