mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-17 20:32:25 +03:00
150 lines
5.8 KiB
TypeScript
150 lines
5.8 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
const { openaiResponsesToOpenAIRequest } = await import(
|
|
"../../open-sse/translator/request/openai-responses.ts"
|
|
);
|
|
|
|
interface ChatTool {
|
|
function: { name: string; description?: string; parameters?: unknown };
|
|
}
|
|
interface ChatRequest {
|
|
messages: unknown[];
|
|
tools: ChatTool[];
|
|
}
|
|
|
|
// Helper: drive the Responses->Chat translator with one namespace tool and
|
|
// return the flattened Chat function names in order.
|
|
function flattenNamespace(nsName: string, subNames: string[]): string[] {
|
|
const result = openaiResponsesToOpenAIRequest(
|
|
"any-model",
|
|
{
|
|
input: [
|
|
{
|
|
type: "additional_tools",
|
|
tools: [
|
|
{
|
|
type: "namespace",
|
|
name: nsName,
|
|
tools: subNames.map((name) => ({
|
|
name,
|
|
description: "sub-tool",
|
|
parameters: { type: "object", properties: {} },
|
|
})),
|
|
},
|
|
],
|
|
},
|
|
{ type: "message", role: "user", content: [{ type: "input_text", text: "go" }] },
|
|
],
|
|
},
|
|
false,
|
|
{ provider: "any-provider" }
|
|
) as ChatRequest;
|
|
return result.tools.map((t) => t.function?.name).filter(Boolean) as string[];
|
|
}
|
|
|
|
test("namespace sub-tool with a bare leaf name is flattened to nsName__leaf", () => {
|
|
// Real Codex client shape: container mcp__1mcp, sub-tool name is the bare leaf "tool_list".
|
|
const names = flattenNamespace("mcp__1mcp", ["tool_list", "tool_schema"]);
|
|
assert.deepEqual(names, ["mcp__1mcp__tool_list", "mcp__1mcp__tool_schema"]);
|
|
});
|
|
|
|
test("non-mcp__-prefixed container (multi_agent_v1) is still qualified", () => {
|
|
// Codex adjudicator dispatches by splitting on "__" and routing to the trailing
|
|
// leaf; the prefix is not gated on "mcp__". Empirically, multi_agent_v1__close_agent
|
|
// is accepted and routed to close_agent (failing only on missing args, not the name).
|
|
const names = flattenNamespace("multi_agent_v1", ["close_agent", "spawn_agent"]);
|
|
assert.deepEqual(names, ["multi_agent_v1__close_agent", "multi_agent_v1__spawn_agent"]);
|
|
});
|
|
|
|
test("codex_app and mcp__context_mode namespaces all get the qualified form", () => {
|
|
const ctx = flattenNamespace("mcp__context_mode", ["ctx_search", "ctx_execute"]);
|
|
assert.deepEqual(ctx, ["mcp__context_mode__ctx_search", "mcp__context_mode__ctx_execute"]);
|
|
const app = flattenNamespace("codex_app", ["read_thread_terminal"]);
|
|
assert.deepEqual(app, ["codex_app__read_thread_terminal"]);
|
|
});
|
|
|
|
test("container name ending with __ (mcp__<server>__ convention) collapses to nsName + leaf", () => {
|
|
// The mcp__atlassian__ trailing-"__" container-name convention (documented in
|
|
// open-sse/executors/codex/tools.ts comments) must NOT produce mcp__atlassian____leaf
|
|
// (four underscores). It collapses to mcp__atlassian__leaf (still three trailing chars
|
|
// before the leaf, matching the convention).
|
|
const names = flattenNamespace("mcp__atlassian__", ["read", "write"]);
|
|
assert.deepEqual(names, ["mcp__atlassian__read", "mcp__atlassian__write"]);
|
|
});
|
|
|
|
test("sub-tool name already containing __ (self-prefixed leaf) is preserved verbatim", () => {
|
|
// A sub-tool whose name already carries its own prefix (e.g. a fixture that names a
|
|
// sub-tool "mcp__server__read" directly) is NOT double-prefixed into nsName + "__" + leaf.
|
|
// Real Codex clients never send this shape (they use bare leaf names), but legacy
|
|
// fixtures / unusual test inputs can; the guard keeps them from producing a pathological
|
|
// double-prefixed wire name.
|
|
const names = flattenNamespace("server", ["mcp__server__read"]);
|
|
assert.deepEqual(names, ["mcp__server__read"]);
|
|
});
|
|
|
|
test("empty container name falls back to the bare leaf (no prefix appended)", () => {
|
|
const names = flattenNamespace("", ["bare_tool"]);
|
|
assert.deepEqual(names, ["bare_tool"]);
|
|
});
|
|
|
|
test("namespace flatten still lets adjacent top-level function tools pass through", () => {
|
|
const result = openaiResponsesToOpenAIRequest(
|
|
"any-model",
|
|
{
|
|
input: [
|
|
{
|
|
type: "additional_tools",
|
|
tools: [
|
|
{ type: "function", name: "lookup", parameters: { type: "object", properties: {} } },
|
|
{
|
|
type: "namespace",
|
|
name: "mcp__1mcp",
|
|
tools: [{ name: "tool_list", parameters: { type: "object", properties: {} } }],
|
|
},
|
|
],
|
|
},
|
|
{ type: "message", role: "user", content: [{ type: "input_text", text: "go" }] },
|
|
],
|
|
},
|
|
false,
|
|
{ provider: "any-provider" }
|
|
) as ChatRequest;
|
|
assert.deepEqual(
|
|
result.tools.map((t) => t.function?.name),
|
|
["lookup", "mcp__1mcp__tool_list"]
|
|
);
|
|
});
|
|
|
|
// #8295 — the regression this file was originally meant to guard against: two
|
|
// namespaces sharing a leaf name must not collapse into duplicate Chat tool names.
|
|
test("#8295: cross-namespace leaf collisions produce distinct qualified wire names", () => {
|
|
const result = openaiResponsesToOpenAIRequest(
|
|
"any-model",
|
|
{
|
|
input: [
|
|
{
|
|
type: "additional_tools",
|
|
tools: [
|
|
{
|
|
type: "namespace",
|
|
name: "mcp__codex_apps__atlassian_rovo",
|
|
tools: [{ name: "_search", parameters: { type: "object", properties: {} } }],
|
|
},
|
|
{
|
|
type: "namespace",
|
|
name: "mcp__codex_apps__linear",
|
|
tools: [{ name: "_search", parameters: { type: "object", properties: {} } }],
|
|
},
|
|
],
|
|
},
|
|
{ type: "message", role: "user", content: [{ type: "input_text", text: "go" }] },
|
|
],
|
|
},
|
|
false,
|
|
{ provider: "any-provider" }
|
|
) as ChatRequest;
|
|
const names = result.tools.map((t) => t.function?.name);
|
|
assert.equal(new Set(names).size, names.length, "Chat tool names must be unique");
|
|
});
|