mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-15 19:32:20 +03:00
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.
113 lines
4.0 KiB
TypeScript
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");
|
|
});
|
|
});
|