import assert from 'node:assert/strict'; import test from 'node:test'; import { MemorySaver } from '@langchain/langgraph'; import { createLangGraphOrchestratorRuntime } from './runtime.mjs'; function runSpec(overrides = {}) { return { runId: 'run-shadow-1', requestId: 'request-shadow-1', workflow: { name: 'code-run-v1', version: 1 }, subject: { userId: 'user-1' }, input: { instruction: 'Add an idempotency test', taskType: 'code-change', }, policy: { executionMode: 'observe-only', sideEffectsAllowed: false, }, ...overrides, }; } test('LangGraph runtime checkpoints a deterministic observe-only code workflow', async () => { const runtime = createLangGraphOrchestratorRuntime({ checkpointer: new MemorySaver(), checkpointKind: 'memory', durable: false, }); const state = await runtime.start(runSpec()); assert.equal(state.runId, 'run-shadow-1'); assert.equal(state.status, 'succeeded'); assert.equal(state.phase, 'completed'); assert.equal(state.result.observed, true); assert.equal(state.result.executed, false); assert.equal(state.plan.executorAdapter, 'native-agent-run'); const restored = await runtime.getState('run-shadow-1'); assert.deepEqual(restored, state); const eventPage = await runtime.listEvents('run-shadow-1'); assert.deepEqual( eventPage.events.map((event) => event.type), ['workflow_validated', 'workflow_planned', 'workflow_completed'], ); assert.deepEqual( eventPage.events.map((event) => event.sequence), [1, 2, 3], ); assert.equal(eventPage.nextCursor, 3); assert.equal((await runtime.listEvents('run-shadow-1', { after: 2 })).events.length, 1); }); test('LangGraph runtime is idempotent by run id', async () => { const runtime = createLangGraphOrchestratorRuntime({ checkpointer: new MemorySaver(), }); const first = await runtime.start(runSpec()); const second = await runtime.start(runSpec({ input: { instruction: 'This must not replace the first checkpoint' }, })); assert.deepEqual(second, first); assert.equal((await runtime.listEvents('run-shadow-1')).events.length, 3); }); test('LangGraph runtime rejects execution-enabled and unsupported workflows', async () => { const runtime = createLangGraphOrchestratorRuntime({ checkpointer: new MemorySaver(), }); await assert.rejects( runtime.start(runSpec({ runId: 'run-active', policy: { executionMode: 'active', sideEffectsAllowed: true }, })), (error) => error.code === 'WORKFLOW_OBSERVE_ONLY_REQUIRED', ); await assert.rejects( runtime.start(runSpec({ runId: 'run-unsupported', workflow: { name: 'research-v1', version: 1 }, })), (error) => error.code === 'WORKFLOW_NOT_SUPPORTED' && error.status === 422, ); });