Files
memind/services/orchestrator/runtime.test.mjs
T

89 lines
2.8 KiB
JavaScript

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,
);
});