Files
OmniRoute/tests/unit/text-tool-call-parsing.test.ts
Praveen K Palaniswamy 65e81158ab fix(ollama): route models by advertised capability (#11088)
Landed with the design call resolved per the owner's pick — **option 1**: the synced store is now endpoint-agnostic (persistDiscoveredModels and managedModelImport no longer drop non-chat models at write time), and chat selectability moved to read time (auto-pool expansion in autoStrategy applies filterChatSelectableModels; the models-route projection already had its chatOnly filter). Your discovery test now passes end-to-end (3/3): /api/show capabilities persist per connection and image/embedding requests route through the advertising host.

Reconciliation notes: conflicted areas merged onto the current tip (adobe discovery import, requestedModel preflight signature, resolvedProvider fast-path coexists with the synced-route override — explicit resolution wins); carried base-red drains (#10055 memoization, #11071 test variants) dropped as already-landed; the managed-model-import exclusion test was propagated to the new contract (image/video models persist; the read filter still hides them from chat pickers — pinned by a new assertion). Full battery: 205/206 focused (the one red is a confirmed periodic-timer timing flake on the loaded devbox — 20/20 isolated), autoCombo vitest 30/30, combo suites 46/46, gates + typecheck clean.

Thank you @yourspraveen — the capability probe + routing design was right; it just needed the store contract opened up. Fixes #11087.
2026-08-23 11:45:01 -03:00

113 lines
4.0 KiB
TypeScript

import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { openaiToClaudeResponse } from "../../open-sse/translator/response/openai-to-claude.ts";
import { geminiToClaudeResponse } from "../../open-sse/translator/response/gemini-to-claude.ts";
interface XmlToolCall {
id: string;
name: string;
args: Record<string, string>;
}
interface TestState {
toolCalls: Map<number, unknown>;
nextBlockIndex: number;
_pendingXmlToolCalls: XmlToolCall[];
}
describe("Text Tool Call Parsing Fixes", () => {
it("parses <tool_call> JSON blocks in OpenAI content text", () => {
const chunk = {
choices: [
{
delta: {
content: '<tool_call>{"name":"Write","arguments":{"file_path":"/tmp/test.txt","content":"hello"}}</tool_call>',
},
finish_reason: "stop",
},
],
};
const state: TestState = { toolCalls: new Map(), nextBlockIndex: 0, _pendingXmlToolCalls: [] };
openaiToClaudeResponse(
chunk as unknown as Parameters<typeof openaiToClaudeResponse>[0],
state as unknown as Parameters<typeof openaiToClaudeResponse>[1]
);
assert.equal(state._pendingXmlToolCalls.length, 1);
assert.equal(state._pendingXmlToolCalls[0].name, "Write");
assert.equal(state._pendingXmlToolCalls[0].args.file_path, "/tmp/test.txt");
});
it("parses TOOL_CALL Name: JSON blocks in OpenAI content text", () => {
const chunk = {
choices: [
{
delta: {
content: 'TOOL_CALL Read: {"file_path":"/home/ubuntu/codeatlas-mcp-server/SECURITY.md"}',
},
finish_reason: "stop",
},
],
};
const state: TestState = { toolCalls: new Map(), nextBlockIndex: 0, _pendingXmlToolCalls: [] };
openaiToClaudeResponse(
chunk as unknown as Parameters<typeof openaiToClaudeResponse>[0],
state as unknown as Parameters<typeof openaiToClaudeResponse>[1]
);
assert.equal(state._pendingXmlToolCalls.length, 1);
assert.equal(state._pendingXmlToolCalls[0].name, "Read");
assert.equal(state._pendingXmlToolCalls[0].args.file_path, "/home/ubuntu/codeatlas-mcp-server/SECURITY.md");
});
it("parses standard XML <invoke> blocks in OpenAI content text", () => {
const chunk = {
choices: [
{
delta: {
content: '<invoke name="Bash"><parameter name="command">ls -la</parameter></invoke>',
},
finish_reason: "stop",
},
],
};
const state: TestState = { toolCalls: new Map(), nextBlockIndex: 0, _pendingXmlToolCalls: [] };
openaiToClaudeResponse(
chunk as unknown as Parameters<typeof openaiToClaudeResponse>[0],
state as unknown as Parameters<typeof openaiToClaudeResponse>[1]
);
assert.equal(state._pendingXmlToolCalls.length, 1);
assert.equal(state._pendingXmlToolCalls[0].name, "Bash");
assert.equal(state._pendingXmlToolCalls[0].args.command, "ls -la");
});
it("parses <tool_call> JSON blocks in Gemini content text", () => {
const chunk = {
candidates: [
{
content: {
parts: [
{
text: '<tool_call>{"name":"bash","arguments":{"command":"pwd"}}</tool_call>',
},
],
},
},
],
};
const state: {
messageId: string | null;
model: string;
contentBlockIndex: number;
openTextBlockIdx: number | null;
} = { messageId: null, model: "gemini", contentBlockIndex: 0, openTextBlockIdx: null };
const events = geminiToClaudeResponse(
chunk as unknown as Parameters<typeof geminiToClaudeResponse>[0],
state as unknown as Parameters<typeof geminiToClaudeResponse>[1]
);
const startEvent = (events as Array<{ type: string; content_block?: { type: string; name: string } }>)?.find(
(e) => e.type === "content_block_start" && e.content_block?.type === "tool_use"
);
assert.ok(startEvent, "Should emit tool_use content_block_start");
assert.equal(startEvent?.content_block?.name, "Bash");
});
});