@adhdev/daemon-core 0.9.5 → 0.9.6

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.
@@ -51,6 +51,13 @@ export declare class CliProviderInstance implements ProviderInstance {
51
51
  private runtimeMessages;
52
52
  private lastPersistedHistoryMessages;
53
53
  private lastCanonicalHermesSyncMtimeMs;
54
+ private lastCanonicalHermesExistCheckAt;
55
+ private lastCanonicalHermesWatchPath;
56
+ private lastCanonicalClaudeRebuildMtimeMs;
57
+ private lastCanonicalClaudeCheckAt;
58
+ private cachedSqliteDb;
59
+ private cachedSqliteDbPath;
60
+ private cachedSqliteDbMissingUntil;
54
61
  readonly instanceId: string;
55
62
  private suppressIdleHistoryReplay;
56
63
  private errorMessage;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/session-host-core",
3
- "version": "0.9.5",
3
+ "version": "0.9.6",
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.9.5",
3
+ "version": "0.9.6",
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",
@@ -161,6 +161,16 @@ export class CliProviderInstance implements ProviderInstance {
161
161
  private runtimeMessages: Array<{ key: string; message: ChatMessage }> = [];
162
162
  private lastPersistedHistoryMessages: PersistableCliHistoryMessage[] = [];
163
163
  private lastCanonicalHermesSyncMtimeMs = 0;
164
+ private lastCanonicalHermesExistCheckAt = 0;
165
+ private lastCanonicalHermesWatchPath: string | undefined = undefined;
166
+ private lastCanonicalClaudeRebuildMtimeMs = 0;
167
+ private lastCanonicalClaudeCheckAt = 0;
168
+ private cachedSqliteDb: {
169
+ prepare(sql: string): { get(...values: Array<string | number>): unknown };
170
+ close(): void;
171
+ } | null = null;
172
+ private cachedSqliteDbPath: string | null = null;
173
+ private cachedSqliteDbMissingUntil = 0;
164
174
  readonly instanceId: string;
165
175
  private suppressIdleHistoryReplay = false;
166
176
  private errorMessage: string | undefined = undefined;
@@ -281,7 +291,13 @@ export class CliProviderInstance implements ProviderInstance {
281
291
  timestampFormat?: 'unix_ms' | 'unix_s' | 'iso';
282
292
  }): string | null {
283
293
  const resolvedDbPath = probe.dbPath.replace(/^~/, os.homedir());
284
- if (!fs.existsSync(resolvedDbPath)) return null;
294
+ // Skip existsSync if we already confirmed DB is missing (cache for 10s)
295
+ const now = Date.now();
296
+ if (this.cachedSqliteDbMissingUntil > now) return null;
297
+ if (!fs.existsSync(resolvedDbPath)) {
298
+ this.cachedSqliteDbMissingUntil = now + 10_000;
299
+ return null;
300
+ }
285
301
 
286
302
  const directories = this.getProbeDirectories();
287
303
  const minCreatedAt = Math.max(0, this.startedAt - 60_000);
@@ -486,6 +502,9 @@ export class CliProviderInstance implements ProviderInstance {
486
502
  this.adapter.shutdown();
487
503
  this.monitor.reset();
488
504
  this.appliedEffectKeys.clear();
505
+ try { this.cachedSqliteDb?.close(); } catch { /* noop */ }
506
+ this.cachedSqliteDb = null;
507
+ this.cachedSqliteDbPath = null;
489
508
  }
490
509
 
491
510
  private completedDebounceTimer: NodeJS.Timeout | null = null;
@@ -944,13 +963,38 @@ export class CliProviderInstance implements ProviderInstance {
944
963
  const watchPath = canonicalHistory.watchPath
945
964
  .replace(/^~/, os.homedir())
946
965
  .replace('{{sessionId}}', this.providerSessionId);
947
- if (!fs.existsSync(watchPath)) return false;
966
+ // Throttle existsSync: check file existence at most once per 2s
967
+ const now = Date.now();
968
+ if (watchPath !== this.lastCanonicalHermesWatchPath || now - this.lastCanonicalHermesExistCheckAt >= 2_000) {
969
+ this.lastCanonicalHermesWatchPath = watchPath;
970
+ this.lastCanonicalHermesExistCheckAt = now;
971
+ if (!fs.existsSync(watchPath)) return false;
972
+ } else if (this.lastCanonicalHermesSyncMtimeMs === 0) {
973
+ // First check: file existence not yet confirmed, must verify
974
+ if (!fs.existsSync(watchPath)) return false;
975
+ }
948
976
  const stat = fs.statSync(watchPath);
949
977
  if (stat.mtimeMs <= this.lastCanonicalHermesSyncMtimeMs) return true;
950
978
  rebuilt = rebuildHermesSavedHistoryFromCanonicalSession(this.providerSessionId);
951
979
  if (rebuilt) this.lastCanonicalHermesSyncMtimeMs = stat.mtimeMs;
952
980
  } else if (canonicalHistory.format === 'claude-jsonl') {
981
+ // Throttle: only check for changes at most once per 2s
982
+ const now = Date.now();
983
+ if (now - this.lastCanonicalClaudeCheckAt < 2_000 && this.lastCanonicalClaudeRebuildMtimeMs !== 0) {
984
+ return true;
985
+ }
986
+ this.lastCanonicalClaudeCheckAt = now;
987
+ // Only rebuild if the transcript file has changed since last rebuild
988
+ const claudeProjectsDir = path.join(os.homedir(), '.claude', 'projects');
989
+ const workspaceSegment = typeof this.workingDir === 'string'
990
+ ? this.workingDir.replace(/[\\/]/g, '-').replace(/^-+/, '')
991
+ : '';
992
+ const transcriptFile = path.join(claudeProjectsDir, workspaceSegment, `${this.providerSessionId}.jsonl`);
993
+ let transcriptMtime = 0;
994
+ try { transcriptMtime = fs.statSync(transcriptFile).mtimeMs; } catch { /* not found yet */ }
995
+ if (transcriptMtime > 0 && transcriptMtime <= this.lastCanonicalClaudeRebuildMtimeMs) return true;
953
996
  rebuilt = rebuildClaudeSavedHistoryFromNativeProject(this.providerSessionId, this.workingDir);
997
+ if (rebuilt) this.lastCanonicalClaudeRebuildMtimeMs = transcriptMtime || Date.now();
954
998
  }
955
999
  if (!rebuilt) return false;
956
1000
  const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
@@ -1023,24 +1067,24 @@ export class CliProviderInstance implements ProviderInstance {
1023
1067
  }
1024
1068
 
1025
1069
  private querySqliteText(dbPath: string, query: string, params: Array<string | number>): string | null {
1026
- let db: {
1027
- prepare(sql: string): { get(...values: Array<string | number>): unknown };
1028
- close(): void;
1029
- } | null = null;
1030
1070
  try {
1031
- const DatabaseSync = getDatabaseSync();
1032
- db = new DatabaseSync(dbPath, { readOnly: true });
1033
- const row = db.prepare(query).get(...params) as { id?: unknown } | undefined;
1071
+ if (this.cachedSqliteDb === null || this.cachedSqliteDbPath !== dbPath) {
1072
+ try { this.cachedSqliteDb?.close(); } catch { /* noop */ }
1073
+ this.cachedSqliteDb = null;
1074
+ this.cachedSqliteDbPath = null;
1075
+ const DatabaseSync = getDatabaseSync();
1076
+ this.cachedSqliteDb = new DatabaseSync(dbPath, { readOnly: true });
1077
+ this.cachedSqliteDbPath = dbPath;
1078
+ }
1079
+ const row = this.cachedSqliteDb!.prepare(query).get(...params) as { id?: unknown } | undefined;
1034
1080
  const sessionId = typeof row?.id === 'string' ? row.id.trim() : '';
1035
1081
  return sessionId || null;
1036
1082
  } catch {
1083
+ // Close cached connection on error so we retry fresh next tick
1084
+ try { this.cachedSqliteDb?.close(); } catch { /* noop */ }
1085
+ this.cachedSqliteDb = null;
1086
+ this.cachedSqliteDbPath = null;
1037
1087
  return null;
1038
- } finally {
1039
- try {
1040
- db?.close();
1041
- } catch {
1042
- // noop
1043
- }
1044
1088
  }
1045
1089
  }
1046
1090
  }
@@ -37,6 +37,7 @@ const KNOWN_PROVIDER_FIELDS = new Set<string>([
37
37
  'canonicalHistory',
38
38
  'autoFixProfile',
39
39
  'ideLevelScripts',
40
+ 'allowInputDuringGeneration',
40
41
  'scripts',
41
42
  'vscodeCommands',
42
43
  'inputMethod',