import { test, expect } from 'vitest';
import {
StateGraph,
START,
END,
MemorySaver,
} from '@langchain/langgraph';
import { z } from "zod/v4";
const State = z.object({
my_key: z.string(),
});
const createGraph = () => {
return new StateGraph(State)
.addNode('node1', (state) => ({ my_key: 'hello from node1' }))
.addNode('node2', (state) => ({ my_key: 'hello from node2' }))
.addNode('node3', (state) => ({ my_key: 'hello from node3' }))
.addNode('node4', (state) => ({ my_key: 'hello from node4' }))
.addEdge(START, 'node1')
.addEdge('node1', 'node2')
.addEdge('node2', 'node3')
.addEdge('node3', 'node4')
.addEdge('node4', END);
};
test('partial execution from node2 to node3', async () => {
const uncompiledGraph = createGraph();
const checkpointer = new MemorySaver();
const compiledGraph = uncompiledGraph.compile({ checkpointer });
await compiledGraph.updateState(
{ configurable: { thread_id: '1' } },
// The state passed into node 2 - simulating the state at
// the end of node 1
{ my_key: 'initial_value' },
// Update saved state as if it came from node 1
// Execution will resume at node 2
'node1',
);
const result = await compiledGraph.invoke(
// Resume execution by passing None
null,
{
configurable: { thread_id: '1' },
// Stop after node 3 so that node 4 doesn't run
interruptAfter: ['node3']
},
);
expect(result.my_key).toBe('hello from node3');
});