blob: 6d633c3d171f03301ac6d481af7c17d36ccea78a [file]
import { createTestToolRuntime } from './execution-boundary-test-helpers.js';
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import type { LlmConnection, SessionEvent, SessionHeader, StoredMessage } from '@maka/core';
import { ToolOutcomeUnknownError } from '@maka/core/events';
import type {
RuntimeCommitSink,
ToolOutcomeCommit,
ToolPreparedCommit,
} from '../runtime-commit-sink.js';
import { ToolRuntime, type MakaTool } from '../tool-runtime.js';
describe('ToolRuntime durable boundary', () => {
it('does not invoke the tool or publish a result when T1 fails', async () => {
let implementationCalls = 0;
const harness = makeHarness({
commitToolPrepared: async () => {
throw new Error('T1 unavailable');
},
commitToolOutcome: async () => {
throw new Error('must not reach T2');
},
});
await assert.rejects(
harness.execute(
tool(() => {
implementationCalls += 1;
return { ok: true };
}),
),
/T1 unavailable/,
);
assert.equal(implementationCalls, 0);
assert.equal(
harness.events.some((event) => event.type === 'tool_result'),
false,
);
assert.equal(
harness.messages.some((message) => message.type === 'tool_result'),
false,
);
});
it('does not invoke a tool when another local dispatcher already owns its operation', async () => {
let implementationCalls = 0;
const harness = makeHarness({
commitToolPrepared: async () => ({ created: false, runtimeEventSeq: 1 }),
commitToolOutcome: async () => {
throw new Error('must not reach T2');
},
});
await assert.rejects(
harness.execute(
tool(() => {
implementationCalls += 1;
return { ok: true };
}),
),
/already claimed/,
);
assert.equal(implementationCalls, 0);
assert.deepEqual(
harness.events.map((event) => event.type),
['tool_start'],
);
assert.deepEqual(
harness.messages.map((message) => message.type),
['tool_call'],
);
});
it('refuses durable tool execution when the turn carries no run id', async () => {
let preparedCalls = 0;
let implementationCalls = 0;
const harness = makeHarness(
{
commitToolPrepared: async () => {
preparedCalls += 1;
return { created: true, runtimeEventSeq: 1 };
},
commitToolOutcome: async () => {
throw new Error('must not reach T2');
},
},
undefined,
null,
);
await assert.rejects(
harness.execute(
tool(() => {
implementationCalls += 1;
return { ok: true };
}),
),
/Durable tool execution requires a run id/,
);
assert.equal(preparedCalls, 0);
assert.equal(implementationCalls, 0);
});
it('does not cross T1 when durable dispatch is already aborted', async () => {
let preparedCalls = 0;
let implementationCalls = 0;
const controller = new AbortController();
controller.abort(new Error('stop before start'));
const harness = makeHarness({
commitToolPrepared: async () => {
preparedCalls += 1;
return { created: true, runtimeEventSeq: 1 };
},
commitToolOutcome: async () => {
throw new Error('must not reach T2');
},
});
await assert.rejects(
harness.execute(
tool(() => {
implementationCalls += 1;
return { ok: true };
}),
controller.signal,
),
/stop before start/,
);
assert.equal(preparedCalls, 0);
assert.equal(implementationCalls, 0);
});
it('commits T1 before implementation and T2 before publishing the result', async () => {
const order: string[] = [];
const prepared: ToolPreparedCommit[] = [];
const outcomes: ToolOutcomeCommit[] = [];
const harness = makeHarness(
{
commitToolPrepared: async (input) => {
prepared.push(input);
order.push('t1');
return { created: true, runtimeEventSeq: 1 };
},
commitToolOutcome: async (input) => {
outcomes.push(input);
order.push('t2');
return { created: true, runtimeEventSeq: 2 };
},
},
order,
);
const result = await harness.execute(
tool(() => {
order.push('impl');
return { ok: true, text: 'done' };
}),
);
assert.deepEqual(result, { ok: true, text: 'done' });
assert.deepEqual(order, ['t1', 'impl', 't2', 'published-result']);
assert.equal(prepared[0]?.runtimeEvent.content?.kind, 'function_call');
assert.equal(
prepared[0]?.dispatchRuntimeEvent.actions?.toolDispatch?.protocol,
't1_after_preflight_v1',
);
assert.equal(prepared[0]?.dispatchRuntimeEvent.content, undefined);
assert.equal(outcomes[0]?.runtimeEvent.content?.kind, 'function_response');
assert.equal(prepared[0]?.operationId, outcomes[0]?.operationId);
assert.equal(prepared[0]?.runtimeEvent.refs?.operationId, prepared[0]?.operationId);
assert.equal(prepared[0]?.dispatchRuntimeEvent.refs?.operationId, prepared[0]?.operationId);
assert.equal(outcomes[0]?.runtimeEvent.refs?.operationId, prepared[0]?.operationId);
});
it('rejects an oversized nested result before durable publication', async () => {
const outcomes: ToolOutcomeCommit[] = [];
const harness = makeHarness({
commitToolPrepared: async () => ({ created: true, runtimeEventSeq: 1 }),
commitToolOutcome: async (input) => {
outcomes.push(input);
return { created: true, runtimeEventSeq: 2 };
},
});
const oversized = { text: 'x'.repeat(128) };
const result = await harness.executeNested(
tool(() => oversized),
32,
);
assert.equal((result as { error?: unknown }).error, 'Tool result byte limit exceeded');
assert.equal(JSON.stringify(harness.events).includes(oversized.text), false);
const durableResult = outcomes[0]?.runtimeEvent.content;
assert.equal(
durableResult?.kind === 'function_response'
? JSON.stringify(durableResult.result).includes(oversized.text)
: false,
false,
);
});
it('uses serialized bytes before publishing a nested string result', async () => {
const outcomes: ToolOutcomeCommit[] = [];
const harness = makeHarness({
commitToolPrepared: async () => ({ created: true, runtimeEventSeq: 1 }),
commitToolOutcome: async (input) => {
outcomes.push(input);
return { created: true, runtimeEventSeq: 2 };
},
});
const result = await harness.executeNested(
tool(() => '\0'.repeat(10)),
32,
);
assert.equal((result as { error?: unknown }).error, 'Tool result byte limit exceeded');
assert.equal(outcomes.length, 1);
assert.equal(outcomes[0]?.runtimeEvent.content?.kind, 'function_response');
assert.equal(
outcomes[0]?.runtimeEvent.content?.kind === 'function_response' &&
outcomes[0].runtimeEvent.content.isError,
true,
);
assert.equal(JSON.stringify(outcomes).includes('\\u0000'), false);
assert.equal(JSON.stringify(harness.events).includes('\\u0000'), false);
});
it('rejects an array whose toJSON expands beyond the nested result limit', async () => {
const outcomes: ToolOutcomeCommit[] = [];
const harness = makeHarness({
commitToolPrepared: async () => ({ created: true, runtimeEventSeq: 1 }),
commitToolOutcome: async (input) => {
outcomes.push(input);
return { created: true, runtimeEventSeq: 2 };
},
});
const resultArray: unknown[] = [];
Object.defineProperty(resultArray, 'toJSON', {
value: () => 'x'.repeat(128),
});
const result = await harness.executeNested(
tool(() => resultArray),
32,
);
assert.equal((result as { error?: unknown }).error, 'Tool result byte limit exceeded');
assert.equal(JSON.stringify(outcomes).includes('x'.repeat(128)), false);
assert.equal(JSON.stringify(harness.events).includes('x'.repeat(128)), false);
});
it('rejects a non-JSON nested result before coercion can expand it', async () => {
const outcomes: ToolOutcomeCommit[] = [];
const harness = makeHarness({
commitToolPrepared: async () => ({ created: true, runtimeEventSeq: 1 }),
commitToolOutcome: async (input) => {
outcomes.push(input);
return { created: true, runtimeEventSeq: 2 };
},
});
const callable = () => null;
callable.toString = () => 'NON_JSON_RESULT'.repeat(32);
const result = await harness.executeNested(
tool(() => callable),
32,
);
assert.equal((result as { error?: unknown }).error, 'Tool result byte limit exceeded');
assert.equal(JSON.stringify(outcomes).includes('NON_JSON_RESULT'), false);
assert.equal(JSON.stringify(harness.events).includes('NON_JSON_RESULT'), false);
});
it('persists nested CodeMode identity across durable and legacy tool activity', async () => {
const prepared: ToolPreparedCommit[] = [];
const outcomes: ToolOutcomeCommit[] = [];
const harness = makeHarness({
commitToolPrepared: async (input) => {
prepared.push(input);
return { created: true, runtimeEventSeq: 1 };
},
commitToolOutcome: async (input) => {
outcomes.push(input);
return { created: true, runtimeEventSeq: 2 };
},
});
await harness.executeNested(tool(() => ({ ok: true })));
for (const event of [
prepared[0]?.runtimeEvent,
prepared[0]?.dispatchRuntimeEvent,
outcomes[0]?.runtimeEvent,
]) {
assert.equal(event?.origin, 'code_mode');
assert.equal(event?.modelVisibility, 'hidden');
assert.equal(event?.refs?.parentToolCallId, 'exec-1');
assert.equal(event?.refs?.parentOperationId, 'exec-op-1');
}
for (const event of harness.events) {
if (event.type !== 'tool_start' && event.type !== 'tool_result') continue;
assert.equal(event.origin, 'code_mode');
assert.equal(event.modelVisibility, 'hidden');
assert.equal(event.parentToolCallId, 'exec-1');
assert.equal(event.parentOperationId, 'exec-op-1');
}
for (const message of harness.messages) {
if (message.type !== 'tool_call' && message.type !== 'tool_result') continue;
assert.equal(message.origin, 'code_mode');
assert.equal(message.modelVisibility, 'hidden');
assert.equal(message.parentToolCallId, 'exec-1');
assert.equal(message.parentOperationId, 'exec-op-1');
}
});
it('links nested live output to the outer exec activity', async () => {
const harness = makeHarness({
commitToolPrepared: async () => ({ created: true, runtimeEventSeq: 1 }),
commitToolOutcome: async () => ({ created: true, runtimeEventSeq: 2 }),
});
await harness.executeNested(
tool((_input, context) => {
context.emitOutput('stdout', 'working\n');
return { ok: true };
}),
);
const output = harness.events.find((event) => event.type === 'tool_output_delta');
assert.ok(output);
assert.equal(output.origin, 'code_mode');
assert.equal(output.modelVisibility, 'hidden');
assert.equal(output.parentToolCallId, 'exec-1');
assert.equal(output.parentOperationId, 'exec-op-1');
});
it('retains nested identity when the tool settles with an error', async () => {
const harness = makeHarness({
commitToolPrepared: async () => ({ created: true, runtimeEventSeq: 1 }),
commitToolOutcome: async () => ({ created: true, runtimeEventSeq: 2 }),
});
await harness.executeNested(
tool(() => {
throw new Error('nested failure');
}),
);
const result = harness.events.find(
(event): event is Extract<SessionEvent, { type: 'tool_result' }> =>
event.type === 'tool_result' && event.toolUseId === 'nested-call-1',
);
assert.ok(result);
assert.equal(result.isError, true);
assert.equal(result.origin, 'code_mode');
assert.equal(result.modelVisibility, 'hidden');
assert.equal(result.parentToolCallId, 'exec-1');
assert.equal(result.parentOperationId, 'exec-op-1');
const stored = harness.messages.find(
(message): message is Extract<StoredMessage, { type: 'tool_result' }> =>
message.type === 'tool_result' && message.toolUseId === 'nested-call-1',
);
assert.equal(stored?.origin, 'code_mode');
assert.equal(stored?.modelVisibility, 'hidden');
});
it('wraps business-domain kind values as canonical JSON tool results', async () => {
const outcomes: ToolOutcomeCommit[] = [];
const harness = makeHarness({
commitToolPrepared: async () => ({ created: true, runtimeEventSeq: 1 }),
commitToolOutcome: async (input) => {
outcomes.push(input);
return { created: true, runtimeEventSeq: 2 };
},
});
const output = {
kind: 'plan_submitted',
proposal: { proposalId: 'proposal-1' },
storeVersion: 1,
};
assert.deepEqual(await harness.execute(tool(() => output)), output);
const response = outcomes[0]?.runtimeEvent.content;
assert.equal(response?.kind, 'function_response');
assert.deepEqual(response?.kind === 'function_response' ? response.result : undefined, {
kind: 'json',
value: output,
});
const message = harness.messages.find((candidate) => candidate.type === 'tool_result');
assert.deepEqual(message?.type === 'tool_result' ? message.content : undefined, {
kind: 'json',
value: output,
});
});
it('does not publish an implementation result when T2 fails', async () => {
let implementationCalls = 0;
const harness = makeHarness({
commitToolPrepared: async () => ({ created: true, runtimeEventSeq: 1 }),
commitToolOutcome: async () => {
throw new Error('T2 unavailable');
},
});
await assert.rejects(
harness.execute(
tool(() => {
implementationCalls += 1;
return { ok: true };
}),
),
/T2 unavailable/,
);
assert.equal(implementationCalls, 1);
assert.equal(
harness.events.some((event) => event.type === 'tool_result'),
false,
);
assert.equal(
harness.messages.some((message) => message.type === 'tool_result'),
false,
);
});
it('commits a normalized error outcome before returning a thrown tool failure to the model', async () => {
const outcomes: ToolOutcomeCommit[] = [];
const harness = makeHarness({
commitToolPrepared: async () => ({ created: true, runtimeEventSeq: 1 }),
commitToolOutcome: async (input) => {
outcomes.push(input);
return { created: true, runtimeEventSeq: 2 };
},
});
await harness.execute(
tool(() => {
throw new Error('tool exploded');
}),
);
const response = outcomes[0]?.runtimeEvent.content;
assert.equal(response?.kind, 'function_response');
assert.equal(response?.kind === 'function_response' && response.isError, true);
assert.equal(
harness.events.some((event) => event.type === 'tool_result' && event.isError),
true,
);
});
it('commits outcome_unknown as a structured non-retryable tool failure', async () => {
const outcomes: ToolOutcomeCommit[] = [];
const harness = makeHarness({
commitToolPrepared: async () => ({ created: true, runtimeEventSeq: 1 }),
commitToolOutcome: async (input) => {
outcomes.push(input);
return { created: true, runtimeEventSeq: 2 };
},
});
const uncertain = tool(() => {
throw new ToolOutcomeUnknownError('Provider disconnected after accepting the action');
});
uncertain.recoveryMode = 'never_auto_retry';
const result = await harness.execute(uncertain);
assert.deepEqual(result, {
error: 'outcome_unknown: Provider disconnected after accepting the action',
});
const response = outcomes[0]?.runtimeEvent.content;
assert.equal(response?.kind, 'function_response');
assert.equal(response?.kind === 'function_response' && response.isError, true);
assert.deepEqual(response?.kind === 'function_response' ? response.result : undefined, {
kind: 'text',
text: 'outcome_unknown: Provider disconnected after accepting the action',
uncertainOutcome: {
code: 'outcome_unknown',
retrySafe: false,
},
});
const message = harness.messages.find((candidate) => candidate.type === 'tool_result');
assert.deepEqual(message?.type === 'tool_result' ? message.content : undefined, {
kind: 'text',
text: 'outcome_unknown: Provider disconnected after accepting the action',
uncertainOutcome: {
code: 'outcome_unknown',
retrySafe: false,
},
});
});
});
// `null` means the turn carries no run id at all; `undefined` keeps the default.
function makeHarness(sink: RuntimeCommitSink, order?: string[], runId: string | null = 'run-1') {
const messages: StoredMessage[] = [];
const events: SessionEvent[] = [];
const runtime = createTestToolRuntime({
sessionId: 'session-1',
header: header(),
connection: connection(),
modelId: 'model-1',
appendMessage: async (message) => {
messages.push(message);
},
newId: nextId(),
now: nextNow(),
getPermissionPauseTarget: () => null,
...(runId ? { runId } : {}),
runtimeCommitSink: sink,
});
return {
messages,
events,
execute: async (target: MakaTool, abortSignal: AbortSignal = new AbortController().signal) =>
(
await runtime.settleToolCall({
tool: target,
turnId: 'turn-1',
toolCallId: 'provider-call-1',
input: {},
abortSignal,
eventSink: {
push: (event) => {
events.push(event);
if (event.type === 'tool_result') order?.push('published-result');
},
pushAndWaitUntilConsumed: async (event) => {
events.push(event);
if (event.type === 'tool_result') order?.push('published-result');
},
},
})
).result,
executeNested: async (target: MakaTool, maxResultBytes?: number) =>
(
await runtime.settleToolCall({
tool: target,
turnId: 'turn-1',
toolCallId: 'nested-call-1',
input: {},
abortSignal: new AbortController().signal,
eventSink: {
push: (event) => events.push(event),
pushAndWaitUntilConsumed: async (event) => {
events.push(event);
},
},
origin: 'code_mode',
parentToolCallId: 'exec-1',
parentOperationId: 'exec-op-1',
...(maxResultBytes !== undefined ? { maxResultBytes } : {}),
})
).result,
};
}
function tool(impl: MakaTool['impl']): MakaTool {
return {
name: 'Read',
description: 'read',
parameters: {},
recoveryMode: 'replay_safe',
impl,
};
}
function header(): SessionHeader {
return {
id: 'session-1',
workspaceRoot: '/workspace/repo',
cwd: '/workspace/repo',
createdAt: 1,
lastUsedAt: 1,
name: 'test',
titleIsManual: false,
isFlagged: false,
labels: [],
isArchived: false,
status: 'active',
statusUpdatedAt: 1,
hasUnread: false,
backend: 'ai-sdk',
llmConnectionSlug: 'connection-1',
connectionLocked: true,
model: 'model-1',
permissionMode: 'ask',
schemaVersion: 1,
};
}
function connection(): LlmConnection {
return {
slug: 'connection-1',
name: 'test',
providerType: 'openai',
defaultModel: 'model-1',
enabled: true,
createdAt: 1,
updatedAt: 1,
};
}
function nextId(): () => string {
let value = 0;
return () => `id-${++value}`;
}
function nextNow(): () => number {
let value = 0;
return () => ++value;
}