@adhdev/daemon-core 0.9.82-rc.475 → 0.9.82-rc.477
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/dist/commands/chat-commands-read.d.ts +8 -0
- package/dist/commands/chat-commands.d.ts +1 -1
- package/dist/config/state-store.d.ts +30 -0
- package/dist/index.js +231 -34
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +231 -34
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-event-forwarding.d.ts +8 -0
- package/dist/providers/cli-provider-instance.d.ts +19 -0
- package/dist/providers/native-history/antigravity-claim-registry.d.ts +17 -6
- package/dist/sessions/registry.d.ts +20 -0
- package/dist/shared-types.d.ts +12 -0
- package/package.json +3 -3
- package/src/commands/chat-commands-read.ts +114 -13
- package/src/commands/chat-commands.ts +1 -1
- package/src/config/state-store.ts +55 -0
- package/src/mesh/mesh-event-forwarding.ts +38 -0
- package/src/providers/cli-provider-instance.ts +148 -5
- package/src/providers/native-history/antigravity-claim-registry.ts +19 -12
- package/src/providers/native-history/dispatcher.ts +92 -14
- package/src/sessions/registry.ts +38 -0
- package/src/shared-types.ts +12 -0
|
@@ -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 ? "
|
|
413
|
-
const commitShort = readInjected(true ? "
|
|
414
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
415
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
412
|
+
const commit = readInjected(true ? "e565a4d93874e580f3923a562a7a58229af17997" : void 0) ?? "unknown";
|
|
413
|
+
const commitShort = readInjected(true ? "e565a4d9" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
414
|
+
const version = readInjected(true ? "0.9.82-rc.477" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
415
|
+
const builtAt = readInjected(true ? "2026-07-06T18:09:09.172Z" : 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
|
});
|
|
@@ -19292,6 +19311,16 @@ function evaluateMeshEventSuppression(args, ctx) {
|
|
|
19292
19311
|
}
|
|
19293
19312
|
return null;
|
|
19294
19313
|
}
|
|
19314
|
+
function sourceWorkerAutoApproves(components, sessionId) {
|
|
19315
|
+
if (!sessionId) return false;
|
|
19316
|
+
try {
|
|
19317
|
+
const state = components.instanceManager?.getInstance?.(sessionId)?.getState?.();
|
|
19318
|
+
const settings = state?.settings || {};
|
|
19319
|
+
return settings.autoApprove === true;
|
|
19320
|
+
} catch {
|
|
19321
|
+
return false;
|
|
19322
|
+
}
|
|
19323
|
+
}
|
|
19295
19324
|
function injectMeshSystemMessage(components, args) {
|
|
19296
19325
|
const eventSessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
19297
19326
|
const eventNodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
|
|
@@ -19350,6 +19379,11 @@ function injectMeshSystemMessage(components, args) {
|
|
|
19350
19379
|
}
|
|
19351
19380
|
}
|
|
19352
19381
|
const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
|
|
19382
|
+
if (args.event === "agent:waiting_approval" && sourceWorkerAutoApproves(components, eventSessionId)) {
|
|
19383
|
+
LOG.info("MeshEvents", `Suppressed agent:waiting_approval for auto-approving worker session ${eventSessionId || "(unknown)"} (mesh ${args.meshId}) \u2014 modal is resolved locally, coordinator not notified`);
|
|
19384
|
+
traceMeshEventDrop("waiting_approval_auto_approving_worker", traceCtx);
|
|
19385
|
+
return { success: true, forwarded: 0, suppressed: true, autoApprovingWorkerApproval: true };
|
|
19386
|
+
}
|
|
19353
19387
|
const suppression = evaluateMeshEventSuppression(args, {
|
|
19354
19388
|
traceCtx,
|
|
19355
19389
|
eventSessionId,
|
|
@@ -34086,6 +34120,7 @@ init_debug_trace();
|
|
|
34086
34120
|
// src/commands/chat-commands-read.ts
|
|
34087
34121
|
var path16 = __toESM(require("path"));
|
|
34088
34122
|
init_contracts2();
|
|
34123
|
+
init_state_store();
|
|
34089
34124
|
init_coordinator_registry();
|
|
34090
34125
|
init_logger();
|
|
34091
34126
|
init_debug_trace();
|
|
@@ -34441,15 +34476,37 @@ init_chat_message_normalization();
|
|
|
34441
34476
|
var HOT_TAIL_MIN_LIMIT = 60;
|
|
34442
34477
|
var CLI_NATIVE_TRANSCRIPT_PROVIDERS = /* @__PURE__ */ new Set(["codex-cli", "claude-cli", "hermes-cli", "antigravity-cli"]);
|
|
34443
34478
|
var lastBoundProviderSessionIdByMeshSession = /* @__PURE__ */ new Map();
|
|
34444
|
-
|
|
34479
|
+
var persistedProviderSessionPinsHydrated = false;
|
|
34480
|
+
function hydratePersistedProviderSessionPinsOnce() {
|
|
34481
|
+
if (persistedProviderSessionPinsHydrated) return;
|
|
34482
|
+
persistedProviderSessionPinsHydrated = true;
|
|
34483
|
+
try {
|
|
34484
|
+
for (const [key2, value] of Object.entries(loadPersistedProviderSessionPins())) {
|
|
34485
|
+
if (!lastBoundProviderSessionIdByMeshSession.has(key2)) {
|
|
34486
|
+
lastBoundProviderSessionIdByMeshSession.set(key2, value);
|
|
34487
|
+
}
|
|
34488
|
+
}
|
|
34489
|
+
} catch {
|
|
34490
|
+
}
|
|
34491
|
+
}
|
|
34492
|
+
function recordBoundProviderSessionId(h, meshSessionId, providerSessionId) {
|
|
34445
34493
|
const key2 = typeof meshSessionId === "string" ? meshSessionId.trim() : "";
|
|
34446
34494
|
const value = typeof providerSessionId === "string" ? providerSessionId.trim() : "";
|
|
34447
34495
|
if (!key2 || !value) return;
|
|
34496
|
+
try {
|
|
34497
|
+
h.ctx?.sessionRegistry?.setProviderSessionId?.(key2, value);
|
|
34498
|
+
} catch {
|
|
34499
|
+
}
|
|
34448
34500
|
lastBoundProviderSessionIdByMeshSession.set(key2, value);
|
|
34501
|
+
try {
|
|
34502
|
+
recordPersistedProviderSessionPin(key2, value);
|
|
34503
|
+
} catch {
|
|
34504
|
+
}
|
|
34449
34505
|
}
|
|
34450
34506
|
function getBoundProviderSessionIdPin(meshSessionId) {
|
|
34451
34507
|
const key2 = typeof meshSessionId === "string" ? meshSessionId.trim() : "";
|
|
34452
34508
|
if (!key2) return void 0;
|
|
34509
|
+
hydratePersistedProviderSessionPinsOnce();
|
|
34453
34510
|
const pinned = lastBoundProviderSessionIdByMeshSession.get(key2);
|
|
34454
34511
|
return pinned && pinned.trim() ? pinned.trim() : void 0;
|
|
34455
34512
|
}
|
|
@@ -35012,8 +35069,14 @@ function hasSafeNativeHistoryMapping(args) {
|
|
|
35012
35069
|
if (!args.requireWorkspaceContentOverlap) return true;
|
|
35013
35070
|
return hasOverlappingVisibleConversationText(args.nativeMessages, args.ptyMessages || []);
|
|
35014
35071
|
}
|
|
35072
|
+
function effectiveReadSessionId(h, targetSessionId) {
|
|
35073
|
+
const explicit = typeof targetSessionId === "string" ? targetSessionId.trim() : "";
|
|
35074
|
+
if (explicit) return explicit;
|
|
35075
|
+
const current = h.currentSession?.sessionId;
|
|
35076
|
+
return typeof current === "string" ? current.trim() : "";
|
|
35077
|
+
}
|
|
35015
35078
|
function sessionStartedAtMsFromRegistry(h, targetSessionId) {
|
|
35016
|
-
const sid =
|
|
35079
|
+
const sid = effectiveReadSessionId(h, targetSessionId);
|
|
35017
35080
|
if (!sid) return void 0;
|
|
35018
35081
|
const target = h.ctx?.sessionRegistry?.get?.(sid);
|
|
35019
35082
|
return typeof target?.spawnedAtMs === "number" ? target.spawnedAtMs : void 0;
|
|
@@ -35310,7 +35373,7 @@ async function handleChatHistory(h, args) {
|
|
|
35310
35373
|
scripts: provider?.scripts,
|
|
35311
35374
|
sessionStartedAtMs: sessionStartedAtMsFromRegistry(h, args?.targetSessionId),
|
|
35312
35375
|
envOverrides: sessionSpawnEnvFromAdapter(h, args?.targetSessionId),
|
|
35313
|
-
instanceId:
|
|
35376
|
+
instanceId: effectiveReadSessionId(h, args?.targetSessionId) || void 0,
|
|
35314
35377
|
pinnedProviderSessionId: getBoundProviderSessionIdPin(args?.targetSessionId)
|
|
35315
35378
|
}) : readProviderChatHistory(agentStr, {
|
|
35316
35379
|
canonicalHistory: provider?.nativeHistory,
|
|
@@ -35327,7 +35390,7 @@ async function handleChatHistory(h, args) {
|
|
|
35327
35390
|
const messages = Array.isArray(result.messages) ? normalizeAndFilterNativeHistory(h, agentStr, args, result.messages, result?.providerSessionId) : [];
|
|
35328
35391
|
const historyProviderSessionId = typeof result?.providerSessionId === "string" ? result.providerSessionId : readHistorySessionIdFromMessages(messages) || historySessionId;
|
|
35329
35392
|
if (typeof result?.providerSessionId === "string" && result.providerSessionId.trim()) {
|
|
35330
|
-
recordBoundProviderSessionId(args?.targetSessionId, result.providerSessionId.trim());
|
|
35393
|
+
recordBoundProviderSessionId(h, effectiveReadSessionId(h, args?.targetSessionId), result.providerSessionId.trim());
|
|
35331
35394
|
}
|
|
35332
35395
|
const safeMapping = hasSafeNativeHistoryMapping({
|
|
35333
35396
|
historySessionId: lookup === "workspace" ? void 0 : historySessionId,
|
|
@@ -35451,10 +35514,15 @@ async function handleReadChat(h, args) {
|
|
|
35451
35514
|
let nativeHistory = null;
|
|
35452
35515
|
let nativeHistoryError;
|
|
35453
35516
|
if (supportsNative) {
|
|
35517
|
+
const pinnedProviderSessionIdForRead = getBoundProviderSessionIdPin(targetSessionId);
|
|
35518
|
+
const nativeReadSessionIdIsRuntimeFallback = Boolean(
|
|
35519
|
+
targetSessionId && nativeHistoryReadSessionId === targetSessionId && !getExplicitHistorySessionId(args)
|
|
35520
|
+
);
|
|
35521
|
+
const effectiveNativeReadSessionId = nativeReadSessionIdIsRuntimeFallback ? pinnedProviderSessionIdForRead || void 0 : nativeHistoryReadSessionId;
|
|
35454
35522
|
try {
|
|
35455
35523
|
nativeHistory = readCliProviderNativeHistory(agentStr, {
|
|
35456
35524
|
canonicalHistory: provider?.nativeHistory,
|
|
35457
|
-
historySessionId:
|
|
35525
|
+
historySessionId: effectiveNativeReadSessionId,
|
|
35458
35526
|
workspace,
|
|
35459
35527
|
offset: 0,
|
|
35460
35528
|
limit: nativeHistoryLimit,
|
|
@@ -35466,16 +35534,16 @@ async function handleReadChat(h, args) {
|
|
|
35466
35534
|
envOverrides: sessionSpawnEnvFromAdapter(h, args?.targetSessionId),
|
|
35467
35535
|
// Stable per-session identity for antigravity's conversation-claim
|
|
35468
35536
|
// owner token (== session registry sessionId == instance instanceId).
|
|
35469
|
-
instanceId:
|
|
35470
|
-
pinnedProviderSessionId:
|
|
35537
|
+
instanceId: effectiveReadSessionId(h, args?.targetSessionId) || void 0,
|
|
35538
|
+
pinnedProviderSessionId: pinnedProviderSessionIdForRead,
|
|
35471
35539
|
// Last-resort only when no pin was ever recorded for this
|
|
35472
35540
|
// session; the downstream workspace-overlap safety gate
|
|
35473
35541
|
// still filters an aliased session out.
|
|
35474
|
-
allowWorkspaceLatestFallback: !
|
|
35542
|
+
allowWorkspaceLatestFallback: !pinnedProviderSessionIdForRead
|
|
35475
35543
|
});
|
|
35476
35544
|
const resolvedProviderSessionId = typeof nativeHistory?.providerSessionId === "string" ? nativeHistory.providerSessionId.trim() : "";
|
|
35477
35545
|
if (resolvedProviderSessionId) {
|
|
35478
|
-
recordBoundProviderSessionId(targetSessionId, resolvedProviderSessionId);
|
|
35546
|
+
recordBoundProviderSessionId(h, effectiveReadSessionId(h, targetSessionId), resolvedProviderSessionId);
|
|
35479
35547
|
}
|
|
35480
35548
|
} catch (error) {
|
|
35481
35549
|
nativeHistoryError = error;
|
|
@@ -35517,7 +35585,7 @@ async function handleReadChat(h, args) {
|
|
|
35517
35585
|
excludeInProgressTurn: returnedStatus === "waiting_approval",
|
|
35518
35586
|
sessionStartedAtMs,
|
|
35519
35587
|
envOverrides: sessionSpawnEnvFromAdapter(h, args?.targetSessionId),
|
|
35520
|
-
instanceId:
|
|
35588
|
+
instanceId: effectiveReadSessionId(h, args?.targetSessionId) || void 0
|
|
35521
35589
|
});
|
|
35522
35590
|
nativeHistoryError = void 0;
|
|
35523
35591
|
nativeMessages = nativeHistory && Array.isArray(nativeHistory.messages) ? normalizeAndFilterNativeHistory(h, agentStr, args, nativeHistory.messages, nativeHistory.providerSessionId) : [];
|
|
@@ -35739,7 +35807,7 @@ async function handleReadChat(h, args) {
|
|
|
35739
35807
|
scripts: provider?.scripts,
|
|
35740
35808
|
sessionStartedAtMs: sessionStartedAtMsFromRegistry(h, args?.targetSessionId),
|
|
35741
35809
|
envOverrides: sessionSpawnEnvFromAdapter(h, args?.targetSessionId),
|
|
35742
|
-
instanceId:
|
|
35810
|
+
instanceId: effectiveReadSessionId(h, args?.targetSessionId) || void 0,
|
|
35743
35811
|
pinnedProviderSessionId: pinnedProviderSessionIdForHistory,
|
|
35744
35812
|
// Last-resort only when no pin was ever recorded AND the
|
|
35745
35813
|
// runtime fallback did not resolve a real provider session.
|
|
@@ -35758,7 +35826,7 @@ async function handleReadChat(h, args) {
|
|
|
35758
35826
|
const historyMessages = Array.isArray(history?.messages) ? normalizeAndFilterNativeHistory(h, agentStr, args, history.messages, history?.providerSessionId) : [];
|
|
35759
35827
|
const historyProviderSessionId = typeof history?.providerSessionId === "string" ? history.providerSessionId : readHistorySessionIdFromMessages(historyMessages) || effectiveHistorySessionIdForRead;
|
|
35760
35828
|
if (typeof history?.providerSessionId === "string" && history.providerSessionId.trim()) {
|
|
35761
|
-
recordBoundProviderSessionId(targetSid, history.providerSessionId.trim());
|
|
35829
|
+
recordBoundProviderSessionId(h, effectiveReadSessionId(h, targetSid), history.providerSessionId.trim());
|
|
35762
35830
|
}
|
|
35763
35831
|
const mappingSessionId = effectiveHistorySessionIdForRead;
|
|
35764
35832
|
const safeMapping = supportsNative ? hasSafeNativeHistoryMapping({
|
|
@@ -44225,6 +44293,7 @@ function createCliAdapter(provider, workingDir, cliArgs, extraEnv, transportFact
|
|
|
44225
44293
|
}
|
|
44226
44294
|
|
|
44227
44295
|
// src/providers/cli-provider-instance.ts
|
|
44296
|
+
init_state_store();
|
|
44228
44297
|
init_logger();
|
|
44229
44298
|
init_debug_trace();
|
|
44230
44299
|
init_debug_config();
|
|
@@ -44257,13 +44326,10 @@ function normalizeUuid(uuid) {
|
|
|
44257
44326
|
return String(uuid || "").trim().toLowerCase();
|
|
44258
44327
|
}
|
|
44259
44328
|
function antigravityOwnerToken(workspace, sessionStartedAtMs, instanceId) {
|
|
44329
|
+
void workspace;
|
|
44330
|
+
void sessionStartedAtMs;
|
|
44260
44331
|
const iid = typeof instanceId === "string" ? instanceId.trim() : "";
|
|
44261
|
-
|
|
44262
|
-
if (typeof sessionStartedAtMs === "number" && sessionStartedAtMs > 0) {
|
|
44263
|
-
const ws = String(workspace || "").trim().toLowerCase();
|
|
44264
|
-
return `spawn:${ws}:${sessionStartedAtMs}`;
|
|
44265
|
-
}
|
|
44266
|
-
return "";
|
|
44332
|
+
return iid ? `iid:${iid}` : "";
|
|
44267
44333
|
}
|
|
44268
44334
|
function claimAntigravityConversation(uuid, owner, now = Date.now()) {
|
|
44269
44335
|
const key2 = normalizeUuid(uuid);
|
|
@@ -45023,6 +45089,27 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45023
45089
|
senderName: message.senderName,
|
|
45024
45090
|
receivedAt: message.receivedAt
|
|
45025
45091
|
})) : mergedMessages;
|
|
45092
|
+
const adapterOwnsMessagesElsewhereForTail = this.adapter?.chatMessagesOwnedExternally === true;
|
|
45093
|
+
if (adapterOwnsMessagesElsewhereForTail && this.lastCompletionSummary) {
|
|
45094
|
+
const summary = this.lastCompletionSummary;
|
|
45095
|
+
let hasTrailingAssistant = false;
|
|
45096
|
+
for (let i = statusMessages.length - 1; i >= 0; i -= 1) {
|
|
45097
|
+
const m = statusMessages[i];
|
|
45098
|
+
const role = typeof m?.role === "string" ? m.role : "";
|
|
45099
|
+
if (role === "system") continue;
|
|
45100
|
+
if (typeof m?.kind === "string" && m.kind === "tool") continue;
|
|
45101
|
+
hasTrailingAssistant = role === "assistant" && typeof m?.receivedAt === "number" && m.receivedAt >= summary.receivedAt - 1e3;
|
|
45102
|
+
break;
|
|
45103
|
+
}
|
|
45104
|
+
if (!hasTrailingAssistant) {
|
|
45105
|
+
statusMessages.push({
|
|
45106
|
+
role: "assistant",
|
|
45107
|
+
content: summary.content,
|
|
45108
|
+
kind: "standard",
|
|
45109
|
+
receivedAt: summary.receivedAt
|
|
45110
|
+
});
|
|
45111
|
+
}
|
|
45112
|
+
}
|
|
45026
45113
|
const dirName = workingDirBasename(this.workingDir);
|
|
45027
45114
|
const parsedChatStatus = typeof parsedStatus?.status === "string" && parsedStatus.status.trim() ? parsedStatus.status.trim() : void 0;
|
|
45028
45115
|
const suppressStaleParsedBusyStatus = this.shouldSuppressStaleParsedBusyStatus(parsedStatus, adapterStatus);
|
|
@@ -45455,6 +45542,18 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45455
45542
|
completedDebounceTimer = null;
|
|
45456
45543
|
completedDebouncePending = null;
|
|
45457
45544
|
lastExternalCompletionProbe = null;
|
|
45545
|
+
/**
|
|
45546
|
+
* The final assistant summary of the last completed turn, cached at
|
|
45547
|
+
* completion-emit time. For a native-source provider (antigravity) whose
|
|
45548
|
+
* assistant answer lives only in native-history — never in the PTY parse that
|
|
45549
|
+
* feeds activeChat.messages — the dashboard's preview / lastMessageRole /
|
|
45550
|
+
* completionMarker would otherwise never see the answer and show the session
|
|
45551
|
+
* stuck on the user prompt. getState() appends this cached assistant bubble to
|
|
45552
|
+
* the status messages when the PTY tail has none, so those fields reflect the
|
|
45553
|
+
* real last answer with ZERO per-tick native reads (the native read already ran
|
|
45554
|
+
* once at completion). Reset on the next turn's start.
|
|
45555
|
+
*/
|
|
45556
|
+
lastCompletionSummary = null;
|
|
45458
45557
|
async enforceFreshSessionLaunchIfNeeded() {
|
|
45459
45558
|
const scriptName = getForcedNewSessionScriptName(this.provider, this.launchMode);
|
|
45460
45559
|
if (!scriptName) return;
|
|
@@ -45518,8 +45617,15 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45518
45617
|
readExternalCompletionMessages() {
|
|
45519
45618
|
const adapterOwnsMessagesElsewhere = this.adapter?.chatMessagesOwnedExternally === true;
|
|
45520
45619
|
if (!adapterOwnsMessagesElsewhere) return null;
|
|
45521
|
-
if (!this.providerSessionId) return null;
|
|
45522
45620
|
if (!isNativeSourceCanonicalHistory(this.provider.nativeHistory)) return null;
|
|
45621
|
+
let resolvedHandle = this.providerSessionId || "";
|
|
45622
|
+
if (!resolvedHandle) {
|
|
45623
|
+
try {
|
|
45624
|
+
const pinned = loadPersistedProviderSessionPins()[this.instanceId];
|
|
45625
|
+
if (typeof pinned === "string" && pinned.trim()) resolvedHandle = pinned.trim();
|
|
45626
|
+
} catch {
|
|
45627
|
+
}
|
|
45628
|
+
}
|
|
45523
45629
|
if (this.lastExternalCompletionProbe?.sourcePath) {
|
|
45524
45630
|
try {
|
|
45525
45631
|
fs21.statSync(this.lastExternalCompletionProbe.sourcePath);
|
|
@@ -45528,13 +45634,18 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45528
45634
|
}
|
|
45529
45635
|
const restoredHistory = readProviderChatHistory(this.type, {
|
|
45530
45636
|
canonicalHistory: this.provider.nativeHistory,
|
|
45531
|
-
historySessionId:
|
|
45637
|
+
historySessionId: resolvedHandle || void 0,
|
|
45532
45638
|
workspace: this.workingDir,
|
|
45533
45639
|
offset: 0,
|
|
45534
45640
|
limit: Number.MAX_SAFE_INTEGER,
|
|
45535
45641
|
historyBehavior: this.provider.historyBehavior,
|
|
45536
45642
|
scripts: this.provider.scripts,
|
|
45537
45643
|
sessionStartedAtMs: this.startedAt,
|
|
45644
|
+
// The claim owner token must match read_chat's so the exact-bind on our
|
|
45645
|
+
// own conversation stays idempotent rather than looking foreign, and so
|
|
45646
|
+
// the floor-based resolution above claims THIS session's db under its
|
|
45647
|
+
// own owner (never a sibling's).
|
|
45648
|
+
instanceId: this.instanceId,
|
|
45538
45649
|
envOverrides: this.spawnedEnvOverrides(),
|
|
45539
45650
|
forceRefresh: true
|
|
45540
45651
|
});
|
|
@@ -45549,6 +45660,26 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45549
45660
|
);
|
|
45550
45661
|
return restoredHistory.messages;
|
|
45551
45662
|
}
|
|
45663
|
+
/**
|
|
45664
|
+
* The content of the LAST visible assistant bubble in a message list, or ''
|
|
45665
|
+
* when the tail is not an assistant reply. Skips trailing system/tool/activity
|
|
45666
|
+
* bubbles; stops (returns '') at the first user/human message. Used only for
|
|
45667
|
+
* the dashboard tail-repair cache — a display value, not a completion decision.
|
|
45668
|
+
*/
|
|
45669
|
+
lastVisibleAssistantSummary(messages) {
|
|
45670
|
+
if (!Array.isArray(messages)) return "";
|
|
45671
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
45672
|
+
const m = messages[i];
|
|
45673
|
+
const role = typeof m?.role === "string" ? m.role : "";
|
|
45674
|
+
const kind = typeof m?.kind === "string" ? m.kind : "";
|
|
45675
|
+
if (role === "system") continue;
|
|
45676
|
+
if (kind === "tool" || kind === "activity") continue;
|
|
45677
|
+
if (role === "user" || role === "human") return "";
|
|
45678
|
+
if (role === "assistant") return flattenContent(m.content).trim();
|
|
45679
|
+
return "";
|
|
45680
|
+
}
|
|
45681
|
+
return "";
|
|
45682
|
+
}
|
|
45552
45683
|
completionFinalAssistantEvidence(parsedMessages, turnStartedAt) {
|
|
45553
45684
|
const turnClosed = !this.hasAdapterPendingResponse();
|
|
45554
45685
|
if (this.completionHasFinalAssistantMessage(parsedMessages, turnStartedAt)) {
|
|
@@ -45560,8 +45691,13 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45560
45691
|
}
|
|
45561
45692
|
const externalMessages = this.readExternalCompletionMessages();
|
|
45562
45693
|
if (externalMessages) {
|
|
45694
|
+
const present = turnClosed && this.completionHasFinalAssistantMessage(externalMessages, turnStartedAt);
|
|
45695
|
+
const lastVisibleAssistant = this.lastVisibleAssistantSummary(externalMessages);
|
|
45696
|
+
if (lastVisibleAssistant) {
|
|
45697
|
+
this.lastCompletionSummary = { content: lastVisibleAssistant, receivedAt: Date.now() };
|
|
45698
|
+
}
|
|
45563
45699
|
return {
|
|
45564
|
-
present
|
|
45700
|
+
present,
|
|
45565
45701
|
messages: externalMessages,
|
|
45566
45702
|
source: "external-native"
|
|
45567
45703
|
};
|
|
@@ -45581,7 +45717,10 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45581
45717
|
if (adapterOwnsMessagesElsewhere) {
|
|
45582
45718
|
const externalMessages = this.readExternalCompletionMessages();
|
|
45583
45719
|
const externalSummary = externalMessages ? extractFinalSummaryFromMessagesAfter(externalMessages, turnStartedAt) : "";
|
|
45584
|
-
if (externalSummary)
|
|
45720
|
+
if (externalSummary) {
|
|
45721
|
+
this.lastCompletionSummary = { content: externalSummary, receivedAt: Date.now() };
|
|
45722
|
+
return externalSummary;
|
|
45723
|
+
}
|
|
45585
45724
|
return parsedSummary || void 0;
|
|
45586
45725
|
}
|
|
45587
45726
|
return parsedSummary || void 0;
|
|
@@ -46049,6 +46188,10 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
46049
46188
|
* the emitted event, exactly as each inline builder produced before.
|
|
46050
46189
|
*/
|
|
46051
46190
|
emitGeneratingCompleted(opts) {
|
|
46191
|
+
const summary = typeof opts.finalSummary === "string" ? opts.finalSummary.trim() : "";
|
|
46192
|
+
if (summary) {
|
|
46193
|
+
this.lastCompletionSummary = { content: summary, receivedAt: opts.timestamp };
|
|
46194
|
+
}
|
|
46052
46195
|
this.pushEvent({
|
|
46053
46196
|
event: "agent:generating_completed",
|
|
46054
46197
|
chatTitle: opts.chatTitle,
|
|
@@ -46333,6 +46476,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
46333
46476
|
this.completedDebouncePending = null;
|
|
46334
46477
|
}
|
|
46335
46478
|
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
46479
|
+
this.lastCompletionSummary = null;
|
|
46336
46480
|
this.busyEpoch++;
|
|
46337
46481
|
if (this.generatingDebounceTimer) clearTimeout(this.generatingDebounceTimer);
|
|
46338
46482
|
this.generatingDebouncePending = { chatTitle, timestamp: now };
|
|
@@ -51300,6 +51444,13 @@ function createNativeHistoryDispatcher(reader) {
|
|
|
51300
51444
|
if (requestedProviderSid && session.providerSessionId && session.providerSessionId !== requestedProviderSid) {
|
|
51301
51445
|
return null;
|
|
51302
51446
|
}
|
|
51447
|
+
let resolvedProviderSessionId = session.providerSessionId;
|
|
51448
|
+
if (reader === "antigravity-cli") {
|
|
51449
|
+
const onDiskUuid = extractAntigravityConversationUuid(session.sourcePath || sourcePath);
|
|
51450
|
+
if (onDiskUuid && (!resolvedProviderSessionId || resolvedProviderSessionId === sessionId)) {
|
|
51451
|
+
resolvedProviderSessionId = onDiskUuid;
|
|
51452
|
+
}
|
|
51453
|
+
}
|
|
51303
51454
|
return {
|
|
51304
51455
|
messages: session.messages.map((m) => ({
|
|
51305
51456
|
role: normalizeRole2(m.role),
|
|
@@ -51308,7 +51459,7 @@ function createNativeHistoryDispatcher(reader) {
|
|
|
51308
51459
|
kind: typeof m.kind === "string" ? m.kind : "standard",
|
|
51309
51460
|
workspace: typeof m.workspace === "string" ? m.workspace : workspace || void 0
|
|
51310
51461
|
})),
|
|
51311
|
-
providerSessionId:
|
|
51462
|
+
providerSessionId: resolvedProviderSessionId,
|
|
51312
51463
|
sourcePath: session.sourcePath,
|
|
51313
51464
|
sourceMtimeMs: session.sourceMtimeMs,
|
|
51314
51465
|
nativeHistoryCoverage: session.nativeHistoryCoverage || "full"
|
|
@@ -51437,6 +51588,17 @@ function resolveRealPath(value) {
|
|
|
51437
51588
|
return value;
|
|
51438
51589
|
}
|
|
51439
51590
|
}
|
|
51591
|
+
function extractAntigravityConversationUuid(sourcePath) {
|
|
51592
|
+
if (!sourcePath) return "";
|
|
51593
|
+
const segments = sourcePath.split(/[\\/]/);
|
|
51594
|
+
const base = segments[segments.length - 1] || "";
|
|
51595
|
+
const baseMatch = /^([0-9a-f-]+)\.(?:db|pb)$/i.exec(base);
|
|
51596
|
+
if (baseMatch && isUuidLikeSessionId2(baseMatch[1])) return baseMatch[1];
|
|
51597
|
+
for (const seg of segments) {
|
|
51598
|
+
if (isUuidLikeSessionId2(seg)) return seg;
|
|
51599
|
+
}
|
|
51600
|
+
return "";
|
|
51601
|
+
}
|
|
51440
51602
|
var AGY_SPAWN_CLAIM_GRACE_MS = 2e3;
|
|
51441
51603
|
function resolveAntigravityPath(workspace, sessionId, sessionStartedAtMs, instanceId) {
|
|
51442
51604
|
const agyRoot = path34.join(os25.homedir(), ".gemini", "antigravity-cli");
|
|
@@ -51451,10 +51613,24 @@ function resolveAntigravityPath(workspace, sessionId, sessionStartedAtMs, instan
|
|
|
51451
51613
|
const brainRoot2 = path34.join(agyRoot, "brain");
|
|
51452
51614
|
if (fs26.existsSync(brainRoot2)) {
|
|
51453
51615
|
const cutoff = spawnAwareCutoff(sessionStartedAtMs);
|
|
51454
|
-
const
|
|
51455
|
-
|
|
51456
|
-
|
|
51457
|
-
|
|
51616
|
+
const nonEmptyBrain = (uuid, p) => {
|
|
51617
|
+
const t = path34.join(p, ".system_generated", "logs", "transcript.jsonl");
|
|
51618
|
+
return fs26.existsSync(t) && safeSize(t) > 0 ? t : null;
|
|
51619
|
+
};
|
|
51620
|
+
const all = fs26.readdirSync(brainRoot2, { withFileTypes: true }).filter((e) => e.isDirectory() && isUuidLikeSessionId2(e.name)).filter((e) => !isAntigravityConversationClaimedByOther(e.name, owner)).map((e) => {
|
|
51621
|
+
const p = path34.join(brainRoot2, e.name);
|
|
51622
|
+
return { uuid: e.name, p, mtime: safeMtime(p), birth: safeBirthtime(p) };
|
|
51623
|
+
}).filter((e) => e.mtime >= cutoff);
|
|
51624
|
+
let ordered = [];
|
|
51625
|
+
if (sessionStartedAtMs > 0) {
|
|
51626
|
+
const floor = sessionStartedAtMs - AGY_SPAWN_CLAIM_GRACE_MS;
|
|
51627
|
+
ordered = all.filter((e) => (e.birth > 0 ? e.birth : e.mtime) >= floor).sort((a, b) => (a.birth || a.mtime) - (b.birth || b.mtime));
|
|
51628
|
+
} else {
|
|
51629
|
+
ordered = [...all].sort((a, b) => b.mtime - a.mtime);
|
|
51630
|
+
}
|
|
51631
|
+
for (const e of ordered) {
|
|
51632
|
+
const t = nonEmptyBrain(e.uuid, e.p);
|
|
51633
|
+
if (t) {
|
|
51458
51634
|
if (owner) claimAntigravityConversation(e.uuid, owner);
|
|
51459
51635
|
return t;
|
|
51460
51636
|
}
|
|
@@ -51475,6 +51651,7 @@ function pickUnboundConversationDb(convRoot, sessionFloorMs, owner) {
|
|
|
51475
51651
|
} catch {
|
|
51476
51652
|
return null;
|
|
51477
51653
|
}
|
|
51654
|
+
const applyRecencyCutoff = !(sessionFloorMs > 0);
|
|
51478
51655
|
const recencyCutoff = Date.now() - RECENT_WINDOW_MS;
|
|
51479
51656
|
const candidates = [];
|
|
51480
51657
|
for (const entry of entries) {
|
|
@@ -51485,7 +51662,7 @@ function pickUnboundConversationDb(convRoot, sessionFloorMs, owner) {
|
|
|
51485
51662
|
if (isAntigravityConversationClaimedByOther(uuid, owner)) continue;
|
|
51486
51663
|
const p = path34.join(convRoot, entry.name);
|
|
51487
51664
|
const mtime = safeMtime(p);
|
|
51488
|
-
if (mtime < recencyCutoff) continue;
|
|
51665
|
+
if (applyRecencyCutoff && mtime < recencyCutoff) continue;
|
|
51489
51666
|
candidates.push({ path: p, uuid, mtime, birth: safeBirthtime(p) });
|
|
51490
51667
|
}
|
|
51491
51668
|
if (candidates.length === 0) return null;
|
|
@@ -68726,7 +68903,11 @@ var SessionRegistry = class {
|
|
|
68726
68903
|
byInstanceKey = /* @__PURE__ */ new Map();
|
|
68727
68904
|
byParentSessionId = /* @__PURE__ */ new Map();
|
|
68728
68905
|
register(target) {
|
|
68906
|
+
const priorProviderSessionId = this.bySessionId.get(target.sessionId)?.providerSessionId;
|
|
68729
68907
|
this.unregister(target.sessionId);
|
|
68908
|
+
if (priorProviderSessionId && !target.providerSessionId) {
|
|
68909
|
+
target = { ...target, providerSessionId: priorProviderSessionId };
|
|
68910
|
+
}
|
|
68730
68911
|
this.bySessionId.set(target.sessionId, target);
|
|
68731
68912
|
if (target.cdpManagerKey) this.addIndex(this.byManagerKey, target.cdpManagerKey, target.sessionId);
|
|
68732
68913
|
if (target.instanceKey) this.addIndex(this.byInstanceKey, target.instanceKey, target.sessionId);
|
|
@@ -68736,6 +68917,22 @@ var SessionRegistry = class {
|
|
|
68736
68917
|
if (!sessionId) return void 0;
|
|
68737
68918
|
return this.bySessionId.get(sessionId);
|
|
68738
68919
|
}
|
|
68920
|
+
/**
|
|
68921
|
+
* Record the authoritative provider-native conversation id for a session
|
|
68922
|
+
* (SSOT). Idempotent; a no-op when the session is unknown or the value is
|
|
68923
|
+
* empty or unchanged. Never overwrites a known binding with an empty one.
|
|
68924
|
+
* Returns whether the stored value changed.
|
|
68925
|
+
*/
|
|
68926
|
+
setProviderSessionId(sessionId, providerSessionId) {
|
|
68927
|
+
const sid = typeof sessionId === "string" ? sessionId.trim() : "";
|
|
68928
|
+
const value = typeof providerSessionId === "string" ? providerSessionId.trim() : "";
|
|
68929
|
+
if (!sid || !value) return false;
|
|
68930
|
+
const target = this.bySessionId.get(sid);
|
|
68931
|
+
if (!target) return false;
|
|
68932
|
+
if (target.providerSessionId === value) return false;
|
|
68933
|
+
target.providerSessionId = value;
|
|
68934
|
+
return true;
|
|
68935
|
+
}
|
|
68739
68936
|
unregister(sessionId) {
|
|
68740
68937
|
if (!sessionId) return;
|
|
68741
68938
|
const target = this.bySessionId.get(sessionId);
|