blob: be4acd2bbaf0aadf424cf165f080ba6222b5a9cc [file]
import { describe, test } from 'node:test';
import assert from 'node:assert/strict';
import {
canonicalizeToolSet,
toolSchemaCharsForDiagnostics,
computeRequestShapeDiagnostic,
} from '../request-shape.js';
import * as requestShape from '../request-shape.js';
import type { MakaTool } from '../tool-runtime.js';
function tool(name: string): MakaTool {
return {
name,
description: name,
parameters: {},
impl: () => ({}),
};
}
const invalid = tool('invalid');
describe('canonicalizeToolSet active allow-list', () => {
test('a tool absent from the active set is withheld; the set drives visibility', () => {
const { activeTools } = canonicalizeToolSet(
[tool('Read'), tool('Rive'), tool('load_tools')],
invalid,
new Set(['Read', 'load_tools']),
);
assert.ok(activeTools.includes('Read'), 'Read is in the active set');
assert.ok(activeTools.includes('load_tools'), 'load_tools is in the active set');
assert.ok(!activeTools.includes('Rive'), 'Rive is absent from the active set, so hidden');
});
test('a tool becomes active once it is in the active set', () => {
const { activeTools } = canonicalizeToolSet(
[tool('Read'), tool('Rive')],
invalid,
new Set(['Read', 'Rive']),
);
assert.ok(activeTools.includes('Rive'), 'Rive is now in the active set');
});
test('providerTools keeps the full registry for dispatch; invalid present but not advertised', () => {
const { providerTools, activeTools } = canonicalizeToolSet(
[tool('Read'), tool('Rive')],
invalid,
new Set(['Read']),
);
const names = providerTools.map((t) => t.name);
assert.ok(names.includes('Read'));
assert.ok(names.includes('Rive'), 'a hidden tool stays dispatchable in providerTools');
assert.ok(names.includes('invalid'), 'repair target present in providerTools');
assert.ok(!activeTools.includes('invalid'), 'invalid is never advertised to the model');
});
test('omitting the active set advertises every visible tool (full surface), names sorted', () => {
const { activeTools } = canonicalizeToolSet([tool('Write'), tool('Read')], invalid);
assert.deepEqual(activeTools, ['Read', 'Write']);
});
});
describe('diagnostics measure the provider-visible (active) tool subset', () => {
const connection = { providerType: 'openai', slug: 'c' } as never;
function rich(name: string, schema: unknown): MakaTool {
return { name, description: name, parameters: schema, impl: () => ({}) };
}
function diag(
providerTools: MakaTool[],
activeTools: string[],
prior?: ReturnType<typeof computeRequestShapeDiagnostic>,
) {
return computeRequestShapeDiagnostic(
{
connection,
modelId: 'm',
systemPrompt: 's',
providerOptions: {},
providerTools,
activeTools,
priorMessages: [],
},
prior,
);
}
test('char count excludes an inactive tool schema', () => {
const tools = [rich('Read', { a: 1 }), rich('Rive', { big: 'x'.repeat(500) })];
const withoutRive = toolSchemaCharsForDiagnostics(tools, ['Read']);
const withRive = toolSchemaCharsForDiagnostics(tools, ['Read', 'Rive']);
assert.ok(
withRive > withoutRive + 400,
'activating Rive should add its schema chars to the count',
);
});
test('toolSchemaHash ignores an INACTIVE tool schema change', () => {
const a = [rich('Read', { a: 1 }), rich('Rive', { v: 1 })];
const b = [rich('Read', { a: 1 }), rich('Rive', { v: 2 })];
assert.equal(
diag(a, ['Read']).componentHashes.toolSchemaHash,
diag(b, ['Read']).componentHashes.toolSchemaHash,
'a change to an unadvertised schema must not move the hash',
);
});
test('activating a hidden tool moves toolSchemaHash and reports tool_schema_changed', () => {
const tools = [rich('Read', { a: 1 }), rich('Rive', { v: 1 })];
const before = diag(tools, ['Read']);
const after = diag(tools, ['Read', 'Rive'], before);
assert.notEqual(after.componentHashes.toolSchemaHash, before.componentHashes.toolSchemaHash);
assert.equal(after.prefixChangeReason, 'tool_schema_changed');
});
});
describe('prepared provider request capture', () => {
test('records cacheable request segments in provider-prefix order', () => {
const capture = Reflect.get(requestShape, 'capturePreparedProviderRequest') as
| ((input: {
providerId: string;
modelId: string;
instructions: string;
messages: Array<{ role: string; content: string }>;
tools: Array<Record<string, unknown>>;
providerOptions: Record<string, unknown>;
}) => {
requestHash: string;
requestBytes: number;
serializedRequest: string;
segments: Array<{
kind: string;
index: number;
cacheable: boolean;
hash: string;
bytes: number;
role?: string;
}>;
})
| undefined;
assert.equal(typeof capture, 'function');
const result = capture!({
providerId: 'anthropic',
modelId: 'claude-test',
instructions: 'system',
messages: [{ role: 'user', content: 'hello' }],
tools: [{ name: 'Bash', description: 'Run a command', inputSchema: { type: 'object' } }],
providerOptions: { anthropic: { thinking: { type: 'enabled', budgetTokens: 1_024 } } },
});
assert.deepEqual(
result.segments.map(({ kind, index, cacheable, role }) => ({
kind,
index,
cacheable,
...(role ? { role } : {}),
})),
[
{ kind: 'tool_schema', index: 0, cacheable: true },
{ kind: 'system_prompt', index: 0, cacheable: true },
{ kind: 'message', index: 0, cacheable: true, role: 'user' },
{ kind: 'provider_options', index: 0, cacheable: false },
],
);
assert.match(result.requestHash, /^sha256:[a-f0-9]{64}$/);
assert.equal(result.requestBytes, Buffer.byteLength(result.serializedRequest, 'utf8'));
assert.ok(result.segments.every((segment) => segment.bytes > 0));
assert.ok(result.segments.every((segment) => /^sha256:[a-f0-9]{64}$/.test(segment.hash)));
});
test('versions and hashes non-provider-options request parameters for comparison', () => {
const capture = (providerOptions: Record<string, unknown>, maxOutputTokens?: number) =>
requestShape.capturePreparedProviderRequest({
providerId: 'provider',
modelId: 'k3',
instructions: 'system',
messages: [{ role: 'user', content: 'hello' }],
tools: [{ name: 'Read', inputSchema: { type: 'object' } }],
providerOptions,
requestPayload: {
prompt: [{ role: 'user', content: 'hello' }],
tools: [{ name: 'Read', inputSchema: { type: 'object' } }],
providerOptions,
...(maxOutputTokens !== undefined ? { maxOutputTokens } : {}),
},
});
const anthropic = capture({ anthropic: { effort: 'max' } }, 131_072);
const openai = capture({ kimiCodingPlan: { reasoningEffort: 'max' } }, 131_072);
const changedSharedParameter = capture({ kimiCodingPlan: { reasoningEffort: 'max' } }, 32_768);
assert.equal(anthropic.schemaVersion, 2);
assert.equal(
anthropic.requestPayloadWithoutProviderOptionsHash,
openai.requestPayloadWithoutProviderOptionsHash,
);
assert.notEqual(
anthropic.requestPayloadWithoutProviderOptionsHash,
changedSharedParameter.requestPayloadWithoutProviderOptionsHash,
);
});
test('keeps reasoning effort across provider namespaces in the protocol-independent hash', () => {
const hash = (providerOptions: Record<string, unknown>, maxOutputTokens: number) =>
requestShape.capturePreparedProviderRequest({
providerId: 'kimi-coding-plan',
modelId: 'kimi-for-coding',
messages: [{ role: 'user', content: 'hello' }],
tools: [],
providerOptions,
requestPayload: {
prompt: [{ role: 'user', content: 'hello' }],
maxOutputTokens,
providerOptions,
},
}).requestPayloadWithoutProviderOptionsHash;
const anthropicMax = hash(
{
anthropic: {
effort: 'max',
thinking: { type: 'enabled', budgetTokens: 1_024 },
},
},
31_744,
);
const openaiMax = hash({ kimiCodingPlan: { reasoningEffort: 'max' } }, 32_768);
const nativeOpenaiMax = hash({ openai: { reasoningEffort: 'max' } }, 32_768);
const nativeOpenaiHigh = hash({ openai: { reasoningEffort: 'high' } }, 32_768);
const zaiHigh = hash({ 'zai-coding-plan': { reasoningEffort: 'high' } }, 32_768);
const zaiLow = hash({ 'zai-coding-plan': { reasoningEffort: 'low' } }, 32_768);
assert.equal(anthropicMax, openaiMax);
assert.equal(anthropicMax, nativeOpenaiMax);
assert.equal(nativeOpenaiHigh, zaiHigh);
assert.notEqual(zaiHigh, zaiLow);
assert.notEqual(anthropicMax, hash({ kimiCodingPlan: { reasoningEffort: 'low' } }, 32_768));
assert.notEqual(anthropicMax, hash({ kimiCodingPlan: { reasoningEffort: 'none' } }, 32_768));
});
test('normalizes disabled Anthropic reasoning to OpenAI none', () => {
const hash = (providerOptions: Record<string, unknown>) =>
requestShape.capturePreparedProviderRequest({
providerId: 'provider',
modelId: 'model',
messages: [{ role: 'user', content: 'hello' }],
tools: [],
providerOptions,
requestPayload: {
prompt: [{ role: 'user', content: 'hello' }],
maxOutputTokens: 32_768,
providerOptions,
},
}).requestPayloadWithoutProviderOptionsHash;
assert.equal(
hash({ anthropic: { thinking: { type: 'disabled' } } }),
hash({ openai: { reasoningEffort: 'none' } }),
);
});
test('normalizes Google thinking level to OpenAI reasoning effort', () => {
const hash = (providerOptions: Record<string, unknown>) =>
requestShape.capturePreparedProviderRequest({
providerId: 'provider',
modelId: 'model',
messages: [{ role: 'user', content: 'hello' }],
tools: [],
providerOptions,
requestPayload: {
prompt: [{ role: 'user', content: 'hello' }],
maxOutputTokens: 32_768,
providerOptions,
},
}).requestPayloadWithoutProviderOptionsHash;
assert.equal(
hash({ google: { thinkingConfig: { includeThoughts: true, thinkingLevel: 'high' } } }),
hash({ openai: { reasoningEffort: 'high' } }),
);
});
test('normalizes zero Google thinking budget to OpenAI none', () => {
const hash = (providerOptions: Record<string, unknown>) =>
requestShape.capturePreparedProviderRequest({
providerId: 'provider',
modelId: 'model',
messages: [{ role: 'user', content: 'hello' }],
tools: [],
providerOptions,
requestPayload: {
prompt: [{ role: 'user', content: 'hello' }],
maxOutputTokens: 32_768,
providerOptions,
},
}).requestPayloadWithoutProviderOptionsHash;
assert.equal(
hash({ google: { thinkingConfig: { thinkingBudget: 0 } } }),
hash({ openai: { reasoningEffort: 'none' } }),
);
});
test('normalizes disabled Cloudflare thinking to OpenAI none', () => {
const hash = (providerOptions: Record<string, unknown>) =>
requestShape.capturePreparedProviderRequest({
providerId: 'provider',
modelId: 'model',
messages: [{ role: 'user', content: 'hello' }],
tools: [],
providerOptions,
requestPayload: {
prompt: [{ role: 'user', content: 'hello' }],
maxOutputTokens: 32_768,
providerOptions,
},
}).requestPayloadWithoutProviderOptionsHash;
assert.equal(
hash({
'cloudflare-workers-ai': { chat_template_kwargs: { thinking: false } },
}),
hash({ openai: { reasoningEffort: 'none' } }),
);
});
test('normalizes Anthropic thinking budget into the protocol-independent output limit', () => {
const capture = (providerOptions: Record<string, unknown>, maxOutputTokens: number) =>
requestShape.capturePreparedProviderRequest({
providerId: 'kimi-coding-plan',
modelId: 'kimi-for-coding',
instructions: 'system',
messages: [{ role: 'user', content: 'hello' }],
tools: [],
providerOptions,
requestPayload: {
prompt: [{ role: 'user', content: 'hello' }],
maxOutputTokens,
providerOptions,
},
});
const anthropic = capture(
{ anthropic: { thinking: { type: 'enabled', budgetTokens: 1_024 } } },
31_744,
);
const openai = capture({ maka: { kimiReasoningField: 'reasoning_content' } }, 32_768);
assert.equal(
anthropic.requestPayloadWithoutProviderOptionsHash,
openai.requestPayloadWithoutProviderOptionsHash,
);
assert.notEqual(anthropic.requestHash, openai.requestHash);
});
test('excludes provider metadata nested in prompt messages and parts', () => {
const capture = (prompt: unknown[], tools: unknown[] = []) =>
requestShape.capturePreparedProviderRequest({
providerId: 'provider',
modelId: 'model',
messages: prompt,
tools,
requestPayload: { prompt, tools },
});
const sharedPrompt = [
{
role: 'assistant',
content: [{ type: 'reasoning', text: 'analysis' }],
},
];
const anthropicPrompt = [
{
role: 'assistant',
providerOptions: { anthropic: { cacheControl: { type: 'ephemeral' } } },
content: [
{
type: 'reasoning',
text: 'analysis',
providerOptions: { anthropic: { signature: 'signed-reasoning' } },
},
],
},
];
assert.equal(
capture(anthropicPrompt).requestPayloadWithoutProviderOptionsHash,
capture(sharedPrompt).requestPayloadWithoutProviderOptionsHash,
);
const sharedToolPrompt = [
{
role: 'tool',
content: [
{
type: 'tool-result',
toolCallId: 'call-1',
toolName: 'Inspect',
output: { type: 'content', value: [{ type: 'text', text: 'done' }] },
},
],
},
];
const providerToolPrompt = [
{
...sharedToolPrompt[0],
providerOptions: { anthropic: { cacheControl: { type: 'ephemeral' } } },
content: [
{
...sharedToolPrompt[0]!.content[0],
providerOptions: { anthropic: { toolUseId: 'provider-call-1' } },
output: {
type: 'content',
providerOptions: { anthropic: { resultId: 'provider-result-1' } },
value: [
{
type: 'text',
text: 'done',
providerOptions: { anthropic: { blockId: 'provider-block-1' } },
},
],
},
},
],
},
];
const sharedTools = [{ type: 'function', name: 'Inspect', inputSchema: { type: 'object' } }];
const providerTools = [
{
...sharedTools[0],
providerOptions: { anthropic: { deferLoading: true } },
},
];
assert.equal(
capture(providerToolPrompt, providerTools).requestPayloadWithoutProviderOptionsHash,
capture(sharedToolPrompt, sharedTools).requestPayloadWithoutProviderOptionsHash,
);
});
test('normalizes provider-local tool and approval bookkeeping', () => {
const hash = (prompt: unknown[]) =>
requestShape.capturePreparedProviderRequest({
providerId: 'provider',
modelId: 'model',
messages: prompt,
tools: [],
requestPayload: { prompt, tools: [] },
}).requestPayloadWithoutProviderOptionsHash;
const prompt = (suffix: string, approved: boolean) => [
{
role: 'assistant',
content: [
{
type: 'tool-call',
toolCallId: `call-${suffix}`,
toolName: 'Inspect',
input: { path: 'README.md' },
providerExecuted: suffix === 'anthropic',
},
{
type: 'tool-approval-request',
approvalId: `approval-${suffix}`,
toolCallId: `call-${suffix}`,
isAutomatic: suffix === 'anthropic',
signature: `signature-${suffix}`,
},
],
},
{
role: 'tool',
content: [
{
type: 'tool-result',
toolCallId: `call-${suffix}`,
toolName: 'Inspect',
output: { type: 'text', value: 'done' },
},
{
type: 'tool-approval-response',
approvalId: `approval-${suffix}`,
approved,
providerExecuted: suffix === 'anthropic',
},
],
},
];
assert.equal(hash(prompt('anthropic', true)), hash(prompt('openai', true)));
assert.notEqual(hash(prompt('anthropic', true)), hash(prompt('openai', false)));
});
test('preserves same-named fields inside user data and tool schemas', () => {
const hash = (prompt: unknown[], tools: unknown[] = []) =>
requestShape.capturePreparedProviderRequest({
providerId: 'provider',
modelId: 'model',
messages: prompt,
tools,
requestPayload: { prompt, tools },
}).requestPayloadWithoutProviderOptionsHash;
const toolCall = (value: string) => [
{
role: 'assistant',
content: [
{
type: 'tool-call',
toolCallId: 'call-1',
toolName: 'Inspect',
input: { providerOptions: value },
},
],
},
];
const toolResult = (value: string) => [
{
role: 'tool',
content: [
{
type: 'tool-result',
toolCallId: 'call-1',
toolName: 'Inspect',
output: { type: 'json', value: { providerOptions: value } },
},
],
},
];
const tool = (description: string) => [
{
type: 'function',
name: 'Inspect',
inputSchema: {
type: 'object',
properties: { providerOptions: { type: 'string', description } },
},
},
];
assert.notEqual(hash(toolCall('alpha')), hash(toolCall('bravo')));
assert.notEqual(hash(toolResult('alpha')), hash(toolResult('bravo')));
assert.notEqual(hash([], tool('alpha')), hash([], tool('bravo')));
});
test('finds the first changed cacheable segment by exact content hash', () => {
const capture = requestShape.capturePreparedProviderRequest;
const findFirstChanged = Reflect.get(requestShape, 'findFirstChangedCacheableSegment') as
| ((
current: ReturnType<typeof capture>,
prior: ReturnType<typeof capture>,
) => { kind: string; index: number; role?: string } | undefined)
| undefined;
assert.equal(typeof findFirstChanged, 'function');
const prior = capture({
providerId: 'openai',
modelId: 'gpt-test',
instructions: 'system',
messages: [{ role: 'user', content: 'alpha' }],
tools: [{ name: 'Read', inputSchema: { type: 'object' } }],
providerOptions: { openai: { reasoningEffort: 'low' } },
});
const changedMessage = capture({
providerId: 'openai',
modelId: 'gpt-test',
instructions: 'system',
messages: [{ role: 'user', content: 'bravo' }],
tools: [{ name: 'Read', inputSchema: { type: 'object' } }],
providerOptions: { openai: { reasoningEffort: 'low' } },
});
assert.deepEqual(findFirstChanged!(changedMessage, prior), {
kind: 'message',
index: 0,
role: 'user',
});
const onlyOptionsChanged = capture({
providerId: 'openai',
modelId: 'gpt-test',
instructions: 'system',
messages: [{ role: 'user', content: 'alpha' }],
tools: [{ name: 'Read', inputSchema: { type: 'object' } }],
providerOptions: { openai: { reasoningEffort: 'high' } },
});
assert.equal(findFirstChanged!(onlyOptionsChanged, prior), undefined);
const appendedMessage = capture({
providerId: 'openai',
modelId: 'gpt-test',
instructions: 'system',
messages: [
{ role: 'user', content: 'alpha' },
{ role: 'assistant', content: 'done' },
],
tools: [{ name: 'Read', inputSchema: { type: 'object' } }],
providerOptions: { openai: { reasoningEffort: 'low' } },
});
assert.deepEqual(findFirstChanged!(appendedMessage, prior), {
kind: 'message',
index: 1,
role: 'assistant',
});
});
});