fix(context): properly re-identify snapshot nodes when loaded from disk

When PR cdd482c2e reverted structural snapshot rehydration, it left
toGraph mapping all non-tool parts as NodeType.USER_PROMPT. This caused
findLatestSnapshotBaseline to fail on resumed sessions, starting the Master
State from an empty baseline and leading to catastrophic data loss.
This fix detects the snapshot signature during graph construction to
properly assign NodeType.SNAPSHOT.
This commit is contained in:
Your Name
2026-05-14 21:04:32 +00:00
parent eee1fda092
commit 5e34ea4be3
7 changed files with 87 additions and 21 deletions
+2 -19
View File
@@ -9,7 +9,7 @@ import type {
AgentChatHistory,
HistoryTurn,
} from '../core/agentChatHistory.js';
import { isToolExecution, type ConcreteNode } from './graph/types.js';
import type { ConcreteNode } from './graph/types.js';
import type { ContextEventBus } from './eventBus.js';
import type { ContextTracer } from './tracer.js';
import type { ContextEnvironment } from './pipeline/environment.js';
@@ -235,24 +235,7 @@ export class ContextManager {
}
}
// 2. Identify active tool calls that must NEVER be truncated
const calls = nodes.filter((n) => isToolExecution(n) && n.role === 'model');
const responses = new Set(
nodes
.filter((n) => isToolExecution(n) && n.role === 'user')
.map((n) => n.payload.functionResponse?.id)
.filter((id): id is string => !!id),
);
for (const call of calls) {
const id = call.payload.functionCall?.id;
// If we have a call but no response in the current graph, it's 'in flight'
if (id && !responses.has(id)) {
protectionMap.set(call.id, 'in_flight_tool_call');
}
}
// 3. Any externally requested protections
// 2. Any externally requested protections
for (const id of extraProtectedIds) {
protectionMap.set(id, 'external_active_task');
}