mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 08:35:57 +00:00
feat: add routed online search providers
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import { createExaToolApiOverride, mapExaToolName, prefixExaTool } from "../extensions/exa-tool-prefix.ts";
|
||||
|
||||
test("Exa tools use a provider prefix followed by the original semantic name", () => {
|
||||
assert.equal(mapExaToolName("web_search_exa"), "exa_web_search");
|
||||
assert.equal(mapExaToolName("web_fetch_exa"), "exa_web_fetch");
|
||||
assert.equal(mapExaToolName("web_search_advanced_exa"), "exa_web_search_advanced");
|
||||
assert.equal(mapExaToolName("unrelated_tool"), "unrelated_tool");
|
||||
|
||||
const tool = prefixExaTool({ name: "web_search_exa", label: "MCP: web_search_exa" });
|
||||
assert.equal(tool.name, "exa_web_search");
|
||||
assert.equal(tool.label, "Exa Web Search");
|
||||
});
|
||||
|
||||
test("Exa API override keeps registered and active tool names aligned", () => {
|
||||
const registered: Array<{ name: string; label: string }> = [];
|
||||
let active: string[] = [];
|
||||
const unregistered: string[] = [];
|
||||
const api = createExaToolApiOverride({
|
||||
registerTool(tool: unknown) {
|
||||
registered.push(tool as { name: string; label: string });
|
||||
},
|
||||
setActiveTools(names: string[]) {
|
||||
active = names;
|
||||
},
|
||||
unregisterTool(name: string) {
|
||||
unregistered.push(name);
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
api.registerTool({ name: "web_fetch_exa", label: "MCP: web_fetch_exa" });
|
||||
api.setActiveTools(["read", "web_fetch_exa", "web_fetch_exa"]);
|
||||
api.unregisterTool("web_fetch_exa");
|
||||
|
||||
assert.equal(registered[0]?.name, "exa_web_fetch");
|
||||
assert.equal(registered[0]?.label, "Exa Web Fetch");
|
||||
assert.deepEqual(active, ["read", "exa_web_fetch"]);
|
||||
assert.deepEqual(unregistered, ["exa_web_fetch"]);
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import { prefixTavilyTool } from "../extensions/tavily-tool-prefix.ts";
|
||||
|
||||
test("Tavily override prefixes tool identity and internal tool references", () => {
|
||||
const tool = prefixTavilyTool({
|
||||
name: "web_search",
|
||||
label: "Web Search",
|
||||
description: "Use web_search, then web_fetch with Tavily.",
|
||||
promptSnippet: "Call web_search.",
|
||||
promptGuidelines: ["Use web_fetch after web_search."],
|
||||
parameters: {} as never,
|
||||
execute: async () => ({ content: [{ type: "text" as const, text: "ok" }] }),
|
||||
});
|
||||
|
||||
assert.equal(tool.name, "tavily_web_search");
|
||||
assert.equal(tool.label, "Tavily Web Search");
|
||||
assert.equal(tool.description, "Use tavily_web_search, then tavily_web_fetch with Tavily.");
|
||||
assert.equal(tool.promptSnippet, "Call tavily_web_search.");
|
||||
assert.deepEqual(tool.promptGuidelines, ["Use tavily_web_fetch after tavily_web_search."]);
|
||||
});
|
||||
@@ -44,6 +44,23 @@ test("LSP routing covers navigation and post-edit diagnostics", () => {
|
||||
assert.match(section, /post-edit diagnostics/);
|
||||
});
|
||||
|
||||
test("online search routing selects providers by task", () => {
|
||||
const tavily = buildToolRoutingSection(["tavily_web_search", "tavily_web_fetch"]);
|
||||
assert.match(tavily, /broad discovery when keywords are uncertain/);
|
||||
assert.match(tavily, /news\/recent\/trending topics/);
|
||||
assert.doesNotMatch(tavily, /official or API documentation/);
|
||||
|
||||
const exa = buildToolRoutingSection(["exa_web_search", "exa_web_fetch", "exa_web_search_advanced"]);
|
||||
assert.match(exa, /official or API documentation/);
|
||||
assert.match(exa, /explicitly bound the result count and returned text length/);
|
||||
assert.doesNotMatch(exa, /Chinese-language pages/);
|
||||
|
||||
const keenable = buildToolRoutingSection(["keenable_search", "keenable_fetch"]);
|
||||
assert.match(keenable, /Chinese-language pages, policies and government notices/);
|
||||
assert.match(keenable, /site-restricted search/);
|
||||
assert.match(keenable, /publication-date filtering/);
|
||||
});
|
||||
|
||||
test("routing includes only guidance for active optional tools", () => {
|
||||
const section = buildToolRoutingSection(["read"]);
|
||||
|
||||
@@ -52,6 +69,8 @@ test("routing includes only guidance for active optional tools", () => {
|
||||
assert.doesNotMatch(section, /Use Context Mode/);
|
||||
assert.doesNotMatch(section, /ctx_execute_file is confined/);
|
||||
assert.doesNotMatch(section, /fresh LINE#HASH anchors/);
|
||||
assert.doesNotMatch(section, /Choose one online search provider/);
|
||||
assert.doesNotMatch(section, /broad discovery when keywords are uncertain/);
|
||||
assert.match(section, /Use read only when exact source is needed/);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user