@adhdev/daemon-core 0.9.82-rc.475 → 0.9.82-rc.476

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.
@@ -3,5 +3,13 @@
3
3
  * native-history / source-resolution / normalization helpers they use.
4
4
  */
5
5
  import type { CommandResult, CommandHelpers } from './handler.js';
6
+ /**
7
+ * Test-only: clear the in-memory read-pin map and re-arm cold-start hydration so
8
+ * each test starts from a clean pin state. The on-disk mirror is isolated per
9
+ * test process via ADHDEV_CONFIG_DIR (test/helpers/setup-env.ts); this resets the
10
+ * module-level cache that would otherwise leak a pin across tests sharing the
11
+ * worker. Not part of the runtime contract.
12
+ */
13
+ export declare function __resetProviderSessionPinsForTest(): void;
6
14
  export declare function handleChatHistory(h: CommandHelpers, args: any): Promise<CommandResult>;
7
15
  export declare function handleReadChat(h: CommandHelpers, args: any): Promise<CommandResult>;
@@ -10,5 +10,5 @@
10
10
  export { READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS, buildSendInputSignature } from './chat-commands-shared.js';
11
11
  export { evaluateReadChatNodeWorkspaceScope } from './chat-commands-scope.js';
12
12
  export { sanitizeDebugBundleValue, handleGetChatDebugBundle } from './chat-commands-debug-bundle.js';
13
- export { handleChatHistory, handleReadChat } from './chat-commands-read.js';
13
+ export { handleChatHistory, handleReadChat, __resetProviderSessionPinsForTest } from './chat-commands-read.js';
14
14
  export { handleSendChat, handleListChats, handleNewChat, handleSwitchChat, handleSetMode, handleChangeModel, handleSetThoughtLevel, handleResolveAction, } from './chat-commands-write.js';
@@ -21,6 +21,17 @@ export interface DaemonState {
21
21
  sessionNotificationDismissals: Record<string, string>;
22
22
  /** Current notification unread override ids keyed by stable session target */
23
23
  sessionNotificationUnreadOverrides: Record<string, string>;
24
+ /**
25
+ * Resolved provider-native conversation id for a live session, keyed by the
26
+ * ADHDev/mesh session id. Persisted so it survives a daemon restart: a
27
+ * provider whose on-disk store is keyed by an internally-generated id it
28
+ * never exposes on the CLI (antigravity — no --session-id) can then exact-bind
29
+ * its conversation .db after restart instead of re-running the mtime/recency
30
+ * heuristic, which drops the store once idle and collapses read_chat to the
31
+ * PTY parse (user echo only, assistant tail lost). Mirrors the in-memory read
32
+ * pin (chat-commands-read lastBoundProviderSessionIdByMeshSession).
33
+ */
34
+ sessionProviderSessionPins: Record<string, string>;
24
35
  }
25
36
  /**
26
37
  * Load runtime state from disk
@@ -34,3 +45,22 @@ export declare function saveState(state: DaemonState): void;
34
45
  * Reset runtime state
35
46
  */
36
47
  export declare function resetState(): void;
48
+ /**
49
+ * Load the full persisted session→provider-conversation pin map (sessionId →
50
+ * provider-native conversation id). Survives daemon restart. Empty object when
51
+ * none recorded or the state file is unreadable.
52
+ */
53
+ export declare function loadPersistedProviderSessionPins(): Record<string, string>;
54
+ /**
55
+ * Persist one session→provider-conversation pin. Load-mutate-save against the
56
+ * on-disk state so it survives a daemon restart; a no-op when the value already
57
+ * matches (avoids rewriting state.json on every read). Never clears a pin with an
58
+ * empty value.
59
+ */
60
+ export declare function recordPersistedProviderSessionPin(sessionId: string, providerSessionId: string): void;
61
+ /**
62
+ * Test-only: drop all persisted session→provider-conversation pins from disk.
63
+ * Used by tests that assert a clean "no pin" state so a sibling test's write to
64
+ * the shared per-process ADHDEV_CONFIG_DIR does not leak in.
65
+ */
66
+ export declare function clearPersistedProviderSessionPins(): void;
package/dist/index.js CHANGED
@@ -409,10 +409,10 @@ function readInjected(value) {
409
409
  }
410
410
  function getDaemonBuildInfo() {
411
411
  if (cached) return cached;
412
- const commit = readInjected(true ? "c7b88fafbc63d3fc0de4b93c74facdb5145b8be6" : void 0) ?? "unknown";
413
- const commitShort = readInjected(true ? "c7b88faf" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
- const version = readInjected(true ? "0.9.82-rc.475" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
- const builtAt = readInjected(true ? "2026-07-06T06:24:24.877Z" : void 0);
412
+ const commit = readInjected(true ? "f3bc279bf108da3a23da4e0e33ebdc41d851930c" : void 0) ?? "unknown";
413
+ const commitShort = readInjected(true ? "f3bc279b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
+ const version = readInjected(true ? "0.9.82-rc.476" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
+ const builtAt = readInjected(true ? "2026-07-06T08:19:57.539Z" : void 0);
416
416
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
417
417
  return cached;
418
418
  }
@@ -16694,13 +16694,17 @@ function normalizeState(raw) {
16694
16694
  const sessionNotificationUnreadOverrides = Object.fromEntries(
16695
16695
  Object.entries(isPlainObject2(parsed.sessionNotificationUnreadOverrides) ? parsed.sessionNotificationUnreadOverrides : {}).filter(([, value]) => typeof value === "string" && value.length > 0)
16696
16696
  );
16697
+ const sessionProviderSessionPins = Object.fromEntries(
16698
+ Object.entries(isPlainObject2(parsed.sessionProviderSessionPins) ? parsed.sessionProviderSessionPins : {}).filter(([key2, value]) => typeof key2 === "string" && key2.length > 0 && typeof value === "string" && value.length > 0)
16699
+ );
16697
16700
  return {
16698
16701
  recentActivity,
16699
16702
  savedProviderSessions,
16700
16703
  sessionReads,
16701
16704
  sessionReadMarkers,
16702
16705
  sessionNotificationDismissals,
16703
- sessionNotificationUnreadOverrides
16706
+ sessionNotificationUnreadOverrides,
16707
+ sessionProviderSessionPins
16704
16708
  };
16705
16709
  }
16706
16710
  function loadState() {
@@ -16723,6 +16727,20 @@ function saveState(state) {
16723
16727
  function resetState() {
16724
16728
  saveState({ ...DEFAULT_STATE });
16725
16729
  }
16730
+ function loadPersistedProviderSessionPins() {
16731
+ return { ...loadState().sessionProviderSessionPins };
16732
+ }
16733
+ function recordPersistedProviderSessionPin(sessionId, providerSessionId) {
16734
+ const key2 = typeof sessionId === "string" ? sessionId.trim() : "";
16735
+ const value = typeof providerSessionId === "string" ? providerSessionId.trim() : "";
16736
+ if (!key2 || !value) return;
16737
+ const state = loadState();
16738
+ if (state.sessionProviderSessionPins[key2] === value) return;
16739
+ saveState({
16740
+ ...state,
16741
+ sessionProviderSessionPins: { ...state.sessionProviderSessionPins, [key2]: value }
16742
+ });
16743
+ }
16726
16744
  var import_fs14, import_path11, DEFAULT_STATE;
16727
16745
  var init_state_store = __esm({
16728
16746
  "src/config/state-store.ts"() {
@@ -16736,7 +16754,8 @@ var init_state_store = __esm({
16736
16754
  sessionReads: {},
16737
16755
  sessionReadMarkers: {},
16738
16756
  sessionNotificationDismissals: {},
16739
- sessionNotificationUnreadOverrides: {}
16757
+ sessionNotificationUnreadOverrides: {},
16758
+ sessionProviderSessionPins: {}
16740
16759
  };
16741
16760
  }
16742
16761
  });
@@ -34086,6 +34105,7 @@ init_debug_trace();
34086
34105
  // src/commands/chat-commands-read.ts
34087
34106
  var path16 = __toESM(require("path"));
34088
34107
  init_contracts2();
34108
+ init_state_store();
34089
34109
  init_coordinator_registry();
34090
34110
  init_logger();
34091
34111
  init_debug_trace();
@@ -34441,15 +34461,33 @@ init_chat_message_normalization();
34441
34461
  var HOT_TAIL_MIN_LIMIT = 60;
34442
34462
  var CLI_NATIVE_TRANSCRIPT_PROVIDERS = /* @__PURE__ */ new Set(["codex-cli", "claude-cli", "hermes-cli", "antigravity-cli"]);
34443
34463
  var lastBoundProviderSessionIdByMeshSession = /* @__PURE__ */ new Map();
34464
+ var persistedProviderSessionPinsHydrated = false;
34465
+ function hydratePersistedProviderSessionPinsOnce() {
34466
+ if (persistedProviderSessionPinsHydrated) return;
34467
+ persistedProviderSessionPinsHydrated = true;
34468
+ try {
34469
+ for (const [key2, value] of Object.entries(loadPersistedProviderSessionPins())) {
34470
+ if (!lastBoundProviderSessionIdByMeshSession.has(key2)) {
34471
+ lastBoundProviderSessionIdByMeshSession.set(key2, value);
34472
+ }
34473
+ }
34474
+ } catch {
34475
+ }
34476
+ }
34444
34477
  function recordBoundProviderSessionId(meshSessionId, providerSessionId) {
34445
34478
  const key2 = typeof meshSessionId === "string" ? meshSessionId.trim() : "";
34446
34479
  const value = typeof providerSessionId === "string" ? providerSessionId.trim() : "";
34447
34480
  if (!key2 || !value) return;
34448
34481
  lastBoundProviderSessionIdByMeshSession.set(key2, value);
34482
+ try {
34483
+ recordPersistedProviderSessionPin(key2, value);
34484
+ } catch {
34485
+ }
34449
34486
  }
34450
34487
  function getBoundProviderSessionIdPin(meshSessionId) {
34451
34488
  const key2 = typeof meshSessionId === "string" ? meshSessionId.trim() : "";
34452
34489
  if (!key2) return void 0;
34490
+ hydratePersistedProviderSessionPinsOnce();
34453
34491
  const pinned = lastBoundProviderSessionIdByMeshSession.get(key2);
34454
34492
  return pinned && pinned.trim() ? pinned.trim() : void 0;
34455
34493
  }
@@ -35451,10 +35489,15 @@ async function handleReadChat(h, args) {
35451
35489
  let nativeHistory = null;
35452
35490
  let nativeHistoryError;
35453
35491
  if (supportsNative) {
35492
+ const pinnedProviderSessionIdForRead = getBoundProviderSessionIdPin(targetSessionId);
35493
+ const nativeReadSessionIdIsRuntimeFallback = Boolean(
35494
+ targetSessionId && nativeHistoryReadSessionId === targetSessionId && !getExplicitHistorySessionId(args)
35495
+ );
35496
+ const effectiveNativeReadSessionId = nativeReadSessionIdIsRuntimeFallback ? pinnedProviderSessionIdForRead || void 0 : nativeHistoryReadSessionId;
35454
35497
  try {
35455
35498
  nativeHistory = readCliProviderNativeHistory(agentStr, {
35456
35499
  canonicalHistory: provider?.nativeHistory,
35457
- historySessionId: nativeHistoryReadSessionId,
35500
+ historySessionId: effectiveNativeReadSessionId,
35458
35501
  workspace,
35459
35502
  offset: 0,
35460
35503
  limit: nativeHistoryLimit,
@@ -35467,11 +35510,11 @@ async function handleReadChat(h, args) {
35467
35510
  // Stable per-session identity for antigravity's conversation-claim
35468
35511
  // owner token (== session registry sessionId == instance instanceId).
35469
35512
  instanceId: typeof args?.targetSessionId === "string" ? args.targetSessionId : void 0,
35470
- pinnedProviderSessionId: getBoundProviderSessionIdPin(targetSessionId),
35513
+ pinnedProviderSessionId: pinnedProviderSessionIdForRead,
35471
35514
  // Last-resort only when no pin was ever recorded for this
35472
35515
  // session; the downstream workspace-overlap safety gate
35473
35516
  // still filters an aliased session out.
35474
- allowWorkspaceLatestFallback: !getBoundProviderSessionIdPin(targetSessionId)
35517
+ allowWorkspaceLatestFallback: !pinnedProviderSessionIdForRead
35475
35518
  });
35476
35519
  const resolvedProviderSessionId = typeof nativeHistory?.providerSessionId === "string" ? nativeHistory.providerSessionId.trim() : "";
35477
35520
  if (resolvedProviderSessionId) {
@@ -51300,6 +51343,13 @@ function createNativeHistoryDispatcher(reader) {
51300
51343
  if (requestedProviderSid && session.providerSessionId && session.providerSessionId !== requestedProviderSid) {
51301
51344
  return null;
51302
51345
  }
51346
+ let resolvedProviderSessionId = session.providerSessionId;
51347
+ if (reader === "antigravity-cli") {
51348
+ const onDiskUuid = extractAntigravityConversationUuid(session.sourcePath || sourcePath);
51349
+ if (onDiskUuid && (!resolvedProviderSessionId || resolvedProviderSessionId === sessionId)) {
51350
+ resolvedProviderSessionId = onDiskUuid;
51351
+ }
51352
+ }
51303
51353
  return {
51304
51354
  messages: session.messages.map((m) => ({
51305
51355
  role: normalizeRole2(m.role),
@@ -51308,7 +51358,7 @@ function createNativeHistoryDispatcher(reader) {
51308
51358
  kind: typeof m.kind === "string" ? m.kind : "standard",
51309
51359
  workspace: typeof m.workspace === "string" ? m.workspace : workspace || void 0
51310
51360
  })),
51311
- providerSessionId: session.providerSessionId,
51361
+ providerSessionId: resolvedProviderSessionId,
51312
51362
  sourcePath: session.sourcePath,
51313
51363
  sourceMtimeMs: session.sourceMtimeMs,
51314
51364
  nativeHistoryCoverage: session.nativeHistoryCoverage || "full"
@@ -51437,6 +51487,17 @@ function resolveRealPath(value) {
51437
51487
  return value;
51438
51488
  }
51439
51489
  }
51490
+ function extractAntigravityConversationUuid(sourcePath) {
51491
+ if (!sourcePath) return "";
51492
+ const segments = sourcePath.split(/[\\/]/);
51493
+ const base = segments[segments.length - 1] || "";
51494
+ const baseMatch = /^([0-9a-f-]+)\.(?:db|pb)$/i.exec(base);
51495
+ if (baseMatch && isUuidLikeSessionId2(baseMatch[1])) return baseMatch[1];
51496
+ for (const seg of segments) {
51497
+ if (isUuidLikeSessionId2(seg)) return seg;
51498
+ }
51499
+ return "";
51500
+ }
51440
51501
  var AGY_SPAWN_CLAIM_GRACE_MS = 2e3;
51441
51502
  function resolveAntigravityPath(workspace, sessionId, sessionStartedAtMs, instanceId) {
51442
51503
  const agyRoot = path34.join(os25.homedir(), ".gemini", "antigravity-cli");
@@ -51475,6 +51536,7 @@ function pickUnboundConversationDb(convRoot, sessionFloorMs, owner) {
51475
51536
  } catch {
51476
51537
  return null;
51477
51538
  }
51539
+ const applyRecencyCutoff = !(sessionFloorMs > 0);
51478
51540
  const recencyCutoff = Date.now() - RECENT_WINDOW_MS;
51479
51541
  const candidates = [];
51480
51542
  for (const entry of entries) {
@@ -51485,7 +51547,7 @@ function pickUnboundConversationDb(convRoot, sessionFloorMs, owner) {
51485
51547
  if (isAntigravityConversationClaimedByOther(uuid, owner)) continue;
51486
51548
  const p = path34.join(convRoot, entry.name);
51487
51549
  const mtime = safeMtime(p);
51488
- if (mtime < recencyCutoff) continue;
51550
+ if (applyRecencyCutoff && mtime < recencyCutoff) continue;
51489
51551
  candidates.push({ path: p, uuid, mtime, birth: safeBirthtime(p) });
51490
51552
  }
51491
51553
  if (candidates.length === 0) return null;