mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 10:45:22 +00:00
feat(pi-web-search): 统一 web_search/web_fetch 并由主模型路由搜索厂商
7 个按厂商命名的搜索工具收敛为 2 个统一工具,schema 与提示词不再暴露 provider 概念:web_search 由当前主模型按内置规则在 Tavily/Exa/Keenable 间路由(会话内 LRU 缓存,失败按可用性降级),web_fetch 固定走 Exa 并 静默降级。三家均改为纯 fetch 直连——Exa 直接对 mcp.exa.ai 发 JSON-RPC 并缓存会话,彻底移除 pi-mcp-adapter、@tavily/pi-extension 与 @keenable/pi-search 依赖。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent
6fe6cb29ae
commit
ee1e6999d7
@@ -0,0 +1,47 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import test from "node:test";
|
||||
|
||||
const packageJson = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8")) as {
|
||||
dependencies: Record<string, string>;
|
||||
files: string[];
|
||||
pi: { extensions: string[]; skills: string[] };
|
||||
};
|
||||
|
||||
test("pi-web-search is the single search surface, loading after search-config", () => {
|
||||
const entries = packageJson.pi.extensions;
|
||||
assert.ok(entries.includes("./pi-web-search/index.ts"), "the bundle must load pi-web-search");
|
||||
assert.ok(
|
||||
entries.indexOf("./extensions/search-config.ts") < entries.indexOf("./pi-web-search/index.ts"),
|
||||
"search credentials must load before pi-web-search",
|
||||
);
|
||||
for (const retired of [
|
||||
"./extensions/mcp.ts",
|
||||
"./extensions/tavily-override.ts",
|
||||
"./node_modules/@keenable/pi-search/src/index.ts",
|
||||
]) {
|
||||
assert.equal(entries.includes(retired), false, `${retired} must no longer be loaded`);
|
||||
}
|
||||
});
|
||||
|
||||
test("pi-web-search ships as a maintained file: dependency without upstream search packages", () => {
|
||||
assert.equal(packageJson.dependencies["pi-web-search"], "file:./pi-web-search");
|
||||
assert.ok(packageJson.files.includes("pi-web-search"));
|
||||
assert.equal(packageJson.dependencies["@tavily/pi-extension"], undefined);
|
||||
assert.equal(packageJson.dependencies["@keenable/pi-search"], undefined);
|
||||
assert.equal(packageJson.dependencies["pi-mcp-adapter"], undefined, "Exa is a direct client now — no MCP adapter");
|
||||
});
|
||||
|
||||
test("no extension in the bundle loads the MCP adapter or upstream search extensions", async () => {
|
||||
for (const entry of packageJson.pi.extensions.filter((e) => !e.startsWith("./node_modules/"))) {
|
||||
const source = await readFile(new URL(`../${entry.slice(2)}`, import.meta.url), "utf8");
|
||||
assert.equal(source.includes("pi-mcp-adapter"), false, `${entry} must not import pi-mcp-adapter`);
|
||||
assert.equal(source.includes("@tavily/pi-extension"), false, `${entry} must not import @tavily/pi-extension`);
|
||||
}
|
||||
});
|
||||
|
||||
test("the keenable skill path is gone with the upstream package", () => {
|
||||
for (const skillPath of packageJson.pi.skills) {
|
||||
assert.equal(skillPath.includes("@keenable"), false);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user