@code-yeongyu/senpi 2026.7.24 → 2026.7.25-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -1
- package/dist/beta/omo-local-update.d.ts +207 -0
- package/dist/beta/omo-local-update.d.ts.map +1 -0
- package/dist/beta/omo-local-update.js +708 -0
- package/dist/beta/omo-local-update.js.map +1 -0
- package/dist/core/agent-session.d.ts +13 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +23 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/index.js +20 -17
- package/dist/core/extensions/builtin/config-reload/index.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/log.d.ts +4 -1
- package/dist/core/extensions/builtin/config-reload/log.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/log.js +3 -0
- package/dist/core/extensions/builtin/config-reload/log.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/routine-settings.d.ts +15 -0
- package/dist/core/extensions/builtin/config-reload/routine-settings.d.ts.map +1 -0
- package/dist/core/extensions/builtin/config-reload/routine-settings.js +102 -0
- package/dist/core/extensions/builtin/config-reload/routine-settings.js.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts +48 -0
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +88 -64
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/index.js +2 -4
- package/dist/core/extensions/builtin/websearch/index.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/config.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/config.js +4 -1
- package/dist/core/extensions/builtin/websearch/websearch/config.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/native.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/native.js +2 -4
- package/dist/core/extensions/builtin/websearch/websearch/native.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/renderers.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/renderers.js +20 -8
- package/dist/core/extensions/builtin/websearch/websearch/renderers.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/search.d.ts +6 -1
- package/dist/core/extensions/builtin/websearch/websearch/search.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/search.js +15 -11
- package/dist/core/extensions/builtin/websearch/websearch/search.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/tool.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/tool.js +5 -10
- package/dist/core/extensions/builtin/websearch/websearch/tool.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/types.d.ts +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/types.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/types.js.map +1 -1
- package/dist/core/extensions/types.d.ts +2 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +13 -3
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +19 -1
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +3 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/retry-fallback/controller.d.ts +7 -0
- package/dist/core/retry-fallback/controller.d.ts.map +1 -1
- package/dist/core/retry-fallback/controller.js +13 -0
- package/dist/core/retry-fallback/controller.js.map +1 -1
- package/dist/core/settings-manager.d.ts +7 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +10 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/thinking-levels.d.ts.map +1 -1
- package/dist/core/thinking-levels.js +9 -2
- package/dist/core/thinking-levels.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +6 -0
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +3 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +9 -2
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +9 -2
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +11 -0
- package/dist/package-manager-cli.js.map +1 -1
- package/docs/extensions.md +2 -2
- package/docs/settings.md +11 -0
- package/examples/extensions/message-renderer.ts +2 -2
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +13 -1
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +3 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +3 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +2 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +87 -22
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js +15 -7
- package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js +38 -16
- package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js +9 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js +12 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +19 -11
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +121 -23
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +12 -7
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/simple-options.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/simple-options.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/simple-options.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.d.ts +3 -2
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.js +37 -35
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/radius.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js +11 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models-store.d.ts +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/models-store.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models-store.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.js +5 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +9 -0
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.js +8 -3
- package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.d.ts +30 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.js +70 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/server-fallback-receipt.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +6 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/websearch/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,gCAAgC,EAAE,MAAM,kCAAkC,CAAC;AACjH,OAAO,EAAE,wBAAwB,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAExG,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAG1D,MAAM,UAAU,GAAG,cAAc,CAAC;AAClC,MAAM,UAAU,GAAG,cAAc,CAAC;AAClC,MAAM,qBAAqB,GAAG,2EAA2E,CAAC;AAK1G,4EAA4E;AAC5E,6EAA6E;AAC7E,+EAA+E;AAC/E,gFAAgF;AAChF,6EAA6E;AAC7E,SAAS,sBAAsB,CAAC,KAAyB;IACxD,IAAI,gCAAgC,CAAC,KAAK,CAAC;QAAE,OAAO,2BAA2B,EAAE,CAAC;IAClF,IAAI,6BAA6B,CAAC,KAAK,CAAC;QAAE,OAAO,wBAAwB,EAAE,CAAC;IAC5E,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAM,CAAC,OAAO,WAAW,EAAgB;IACxC,IAAI,KAAK,GAAqB;QAC7B,EAAE,EAAE,KAAK;QACT,MAAM,EAAE,gBAAgB;QACxB,OAAO,EAAE,iGAAiG;KAC1G,CAAC;IAEF,SAAS,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/websearch/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { isAnthropicWebSearchEnabled, supportsNativeAnthropicWebSearch } from \"../anthropic-web-search/index.ts\";\nimport { isOpenaiWebSearchEnabled, supportsNativeOpenAiWebSearch } from \"../openai-web-search/index.ts\";\n\nimport { loadWebsearchConfig } from \"./websearch/config.ts\";\nimport { providerEntryLabel } from \"./websearch/search.ts\";\nimport { createWebSearchTool } from \"./websearch/tool.ts\";\nimport type { ConfigLoadResult, WebsearchConfig } from \"./websearch/types.ts\";\n\nconst STATUS_KEY = \"pi-websearch\";\nconst WIDGET_KEY = \"pi-websearch\";\nconst NATIVE_BYPASS_MESSAGE = \"Native provider web search is handled by the built-in provider extension.\";\n\ntype NativeCapableModel = Parameters<typeof supportsNativeAnthropicWebSearch>[0] &\n\tParameters<typeof supportsNativeOpenAiWebSearch>[0];\n\n// Defer to the provider-native server-side web_search only when the builtin\n// injecting extension will actually add it for this exact model (first-party\n// endpoint or explicit compat opt-in, and not disabled via env). A provider id\n// of \"anthropic\"/\"openai\" alone is not enough: proxied baseUrls (ccapi, quotio,\n// …) never receive the native tool, so bypassing there leaves no web search.\nfunction isProviderNativeBypass(model: NativeCapableModel): boolean {\n\tif (supportsNativeAnthropicWebSearch(model)) return isAnthropicWebSearchEnabled();\n\tif (supportsNativeOpenAiWebSearch(model)) return isOpenaiWebSearchEnabled();\n\treturn false;\n}\n\nexport default function (pi: ExtensionAPI): void {\n\tlet state: ConfigLoadResult = {\n\t\tok: false,\n\t\treason: \"missing_config\",\n\t\tmessage: \"Missing websearch config. Create .pi/websearch.json or ~/.pi/websearch.json before starting pi.\",\n\t};\n\n\tfunction providerList(config: WebsearchConfig): string {\n\t\treturn config.providers.map(providerEntryLabel).join(\", \");\n\t}\n\n\tfunction clearUi(ctx: ExtensionContext): void {\n\t\tif (ctx.hasUI === false) return;\n\t\tctx.ui.setStatus(STATUS_KEY, undefined);\n\t\tctx.ui.setWidget(WIDGET_KEY, undefined);\n\t}\n\n\tfunction updateUi(ctx: ExtensionContext): void {\n\t\tif (ctx.hasUI === false) return;\n\t\tif (state.ok) {\n\t\t\tclearUi(ctx);\n\t\t\treturn;\n\t\t}\n\t\tif (state.reason === \"provider_native_bypass\") {\n\t\t\tclearUi(ctx);\n\t\t\treturn;\n\t\t}\n\t\tclearUi(ctx);\n\t\tctx.ui.notify(state.message, \"error\");\n\t}\n\n\tpi.registerTool(createWebSearchTool(() => state));\n\n\tasync function refreshState(model: NativeCapableModel, ctx: ExtensionContext): Promise<void> {\n\t\tstate = isProviderNativeBypass(model)\n\t\t\t? { ok: false, reason: \"provider_native_bypass\", message: NATIVE_BYPASS_MESSAGE }\n\t\t\t: await loadWebsearchConfig({ cwd: ctx.cwd });\n\t\tupdateUi(ctx);\n\t}\n\n\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\tawait refreshState(ctx.model, ctx);\n\t});\n\n\tpi.on(\"model_select\", async (event, ctx) => {\n\t\tawait refreshState(event.model, ctx);\n\t});\n\n\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\tclearUi(ctx);\n\t});\n\n\tpi.registerCommand(\"websearch\", {\n\t\tdescription: \"Show web search provider status\",\n\t\thandler: async (rawArgs, ctx) => {\n\t\t\tconst args = rawArgs.trim();\n\t\t\tif (args !== \"\" && args !== \"status\") {\n\t\t\t\tctx.ui.notify(\"Usage: /websearch status\", \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (state.ok) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Web search active: strategy=${state.config.strategy}, auto=${state.config.auto ? \"enabled\" : \"disabled\"}, providers=${providerList(state.config)}`,\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tctx.ui.notify(\n\t\t\t\tstate.reason === \"provider_native_bypass\"\n\t\t\t\t\t? `Web search deferred: ${state.message}`\n\t\t\t\t\t: `Web search inactive: ${state.message}`,\n\t\t\t\tstate.reason === \"provider_native_bypass\" ? \"info\" : \"error\",\n\t\t\t);\n\t\t},\n\t});\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/config.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEX,gBAAgB,EAGhB,wBAAwB,EAKxB,mBAAmB,EAEnB,eAAe,EACf,MAAM,YAAY,CAAC;AA2BpB,MAAM,WAAW,iBAAiB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAgID,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,mBAAmB,GAAG,wBAAwB,CAmD5F;AAED,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,eAAe,GACrB,wBAAwB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,CAiBlE;AAWD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA0B/F"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { access, readFile } from "node:fs/promises";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { CONFIG_DIR_NAME } from "../../../../../config.js";
|
|
4
5
|
import { isAllowedProviderBaseUrl } from "./provider-endpoints.js";
|
|
5
6
|
const PROVIDERS = [
|
|
6
7
|
"exa",
|
|
@@ -226,10 +227,12 @@ async function fileExists(path) {
|
|
|
226
227
|
export async function loadWebsearchConfig(options) {
|
|
227
228
|
const home = options.homeDir ?? homedir();
|
|
228
229
|
const paths = [
|
|
230
|
+
join(options.cwd, CONFIG_DIR_NAME, "websearch.json"),
|
|
229
231
|
join(options.cwd, ".pi", "websearch.json"),
|
|
230
232
|
join(home, "websearch.json"),
|
|
233
|
+
join(home, CONFIG_DIR_NAME, "websearch.json"),
|
|
231
234
|
join(home, ".pi", "websearch.json"),
|
|
232
|
-
];
|
|
235
|
+
].filter((path, index, all) => all.indexOf(path) === index);
|
|
233
236
|
for (const path of paths) {
|
|
234
237
|
if (!(await fileExists(path)))
|
|
235
238
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/config.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { isAllowedProviderBaseUrl } from \"./provider-endpoints.ts\";\nimport type {\n\tCodexSearchMode,\n\tConfigLoadResult,\n\tJsonObject,\n\tJsonValue,\n\tProviderValidationResult,\n\tRoutingStrategy,\n\tSearchContextSize,\n\tSearchProvider,\n\tSearchProviderConfig,\n\tSearchProviderEntry,\n\tSearchUserLocation,\n\tWebsearchConfig,\n} from \"./types.ts\";\n\nconst PROVIDERS: readonly SearchProvider[] = [\n\t\"exa\",\n\t\"tavily\",\n\t\"brave\",\n\t\"duckduckgo-html\",\n\t\"serper\",\n\t\"google-cse\",\n\t\"z-ai\",\n\t\"openai\",\n\t\"codex\",\n\t\"anthropic\",\n\t\"perplexity\",\n\t\"xai\",\n\t\"kimi\",\n];\nconst CONTEXT_SIZES: readonly SearchContextSize[] = [\"low\", \"medium\", \"high\"];\nconst CODEX_MODES: readonly CodexSearchMode[] = [\"cached\", \"live\"];\nconst STRATEGIES: readonly RoutingStrategy[] = [\"priority\", \"round-robin\", \"fill-first\"];\nconst DEFAULT_FREE_CONFIG: WebsearchConfig = {\n\tstrategy: \"priority\",\n\tfallback: true,\n\tauto: true,\n\tproviders: [{ id: \"default\", provider: \"duckduckgo-html\", maxResults: 10 }],\n};\n\nexport interface ConfigLoadOptions {\n\tcwd: string;\n\thomeDir?: string;\n}\n\nfunction isJsonObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction oneOf<TValue extends string>(values: readonly TValue[], value: unknown): value is TValue {\n\treturn typeof value === \"string\" && (values as readonly string[]).includes(value);\n}\n\nfunction isStringArray(value: JsonValue | undefined): value is string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction optionalString(value: JsonValue | undefined): string | undefined {\n\treturn typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction optionalNumber(value: JsonValue | undefined): number | undefined {\n\treturn typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction optionalBoolean(value: JsonValue | undefined): boolean | undefined {\n\treturn typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction optionalProvider(value: JsonValue | undefined): SearchProvider | undefined {\n\treturn oneOf(PROVIDERS, value) ? value : undefined;\n}\n\nfunction optionalContextSize(value: JsonValue | undefined): SearchContextSize | undefined {\n\treturn oneOf(CONTEXT_SIZES, value) ? value : undefined;\n}\n\nfunction optionalCodexMode(value: JsonValue | undefined): CodexSearchMode | undefined {\n\treturn oneOf(CODEX_MODES, value) ? value : undefined;\n}\n\nfunction optionalStrategy(value: JsonValue | undefined): RoutingStrategy | undefined {\n\treturn oneOf(STRATEGIES, value) ? value : undefined;\n}\n\nfunction optionalLocation(value: JsonValue | undefined): SearchUserLocation | undefined {\n\tif (!isJsonObject(value)) return undefined;\n\tconst location: SearchUserLocation = {};\n\tconst country = optionalString(value.country);\n\tconst region = optionalString(value.region);\n\tconst city = optionalString(value.city);\n\tconst timezone = optionalString(value.timezone);\n\tif (country) location.country = country;\n\tif (region) location.region = region;\n\tif (city) location.city = city;\n\tif (timezone) location.timezone = timezone;\n\treturn Object.keys(location).length > 0 ? location : undefined;\n}\n\nfunction parseJsonObject(content: string): JsonObject | null {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(content);\n\t} catch {\n\t\treturn null;\n\t}\n\treturn isJsonObject(parsed) ? parsed : null;\n}\n\nfunction providerEntryFromObject(raw: JsonObject): SearchProviderEntry | null {\n\tconst provider = optionalProvider(raw.provider) ?? optionalProvider(raw.backend);\n\tif (!provider) return null;\n\n\tconst config: SearchProviderEntry = { provider };\n\tconst id = optionalString(raw.id);\n\tconst apiKey = optionalString(raw.apiKey);\n\tconst baseUrl = optionalString(raw.baseUrl);\n\tconst searchEngineId = optionalString(raw.searchEngineId);\n\tconst maxResults = optionalNumber(raw.maxResults);\n\tconst model = optionalString(raw.model);\n\tconst codexMode = optionalCodexMode(raw.codexMode);\n\tconst searchContextSize = optionalContextSize(raw.searchContextSize);\n\tconst rawAllowedDomains = raw.allowedDomains;\n\tconst rawBlockedDomains = raw.blockedDomains;\n\tconst allowedDomains = isStringArray(rawAllowedDomains) ? rawAllowedDomains : undefined;\n\tconst blockedDomains = isStringArray(rawBlockedDomains) ? rawBlockedDomains : undefined;\n\tconst userLocation = optionalLocation(raw.userLocation);\n\tconst timeoutMs = optionalNumber(raw.timeoutMs);\n\tconst priority = optionalNumber(raw.priority);\n\tconst weight = optionalNumber(raw.weight);\n\n\tif (id) config.id = id;\n\tif (apiKey) config.apiKey = apiKey;\n\tif (baseUrl) config.baseUrl = baseUrl;\n\tif (searchEngineId) config.searchEngineId = searchEngineId;\n\tif (maxResults) config.maxResults = maxResults;\n\tif (model) config.model = model;\n\tif (codexMode) config.codexMode = codexMode;\n\tif (searchContextSize) config.searchContextSize = searchContextSize;\n\tif (allowedDomains) config.allowedDomains = allowedDomains;\n\tif (blockedDomains) config.blockedDomains = blockedDomains;\n\tif (userLocation) config.userLocation = userLocation;\n\tif (timeoutMs !== undefined) config.timeoutMs = timeoutMs;\n\tif (priority !== undefined) config.priority = priority;\n\tif (weight !== undefined) config.weight = weight;\n\n\treturn config;\n}\n\nfunction configFromObject(raw: JsonObject): WebsearchConfig | null {\n\tconst auto = optionalBoolean(raw.auto) ?? true;\n\tconst providersValue = raw.providers;\n\tconst rawProviders = Array.isArray(providersValue) ? providersValue : undefined;\n\tif (rawProviders) {\n\t\tif (optionalProvider(raw.provider)) return null;\n\t\tconst providers = rawProviders\n\t\t\t.map((value) => (isJsonObject(value) ? providerEntryFromObject(value) : null))\n\t\t\t.filter((entry): entry is SearchProviderEntry => entry !== null);\n\t\tconst strategy = optionalStrategy(raw.strategy) ?? \"priority\";\n\t\tconst fallback = optionalBoolean(raw.fallback) ?? true;\n\t\treturn { strategy, fallback, auto, providers };\n\t}\n\n\tconst provider = providerEntryFromObject(raw);\n\treturn provider ? { strategy: \"priority\", fallback: true, auto, providers: [provider] } : null;\n}\n\nfunction hasApiKey(config: SearchProviderConfig): boolean {\n\treturn typeof config.apiKey === \"string\" && config.apiKey.length > 0;\n}\n\nexport function validateProviderConfig(config: SearchProviderEntry): ProviderValidationResult {\n\tif (!PROVIDERS.includes(config.provider)) {\n\t\treturn { ok: false, reason: \"invalid_config\", message: `Unsupported provider: ${config.provider}` };\n\t}\n\n\tif (config.allowedDomains && config.blockedDomains) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\treason: \"invalid_config\",\n\t\t\tmessage: \"Provider config cannot specify both allowedDomains and blockedDomains.\",\n\t\t};\n\t}\n\n\tif (config.weight !== undefined && config.weight <= 0) {\n\t\treturn { ok: false, reason: \"invalid_config\", message: \"Provider weight must be greater than 0.\" };\n\t}\n\n\tif (config.timeoutMs !== undefined && config.timeoutMs <= 0) {\n\t\treturn { ok: false, reason: \"invalid_config\", message: \"Provider timeoutMs must be greater than 0.\" };\n\t}\n\n\tif (config.baseUrl && !isAllowedProviderBaseUrl(config.baseUrl)) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\treason: \"invalid_config\",\n\t\t\tmessage: `Provider ${config.provider} baseUrl must be a public HTTPS URL without credentials.`,\n\t\t};\n\t}\n\n\tif (config.provider === \"google-cse\" && !config.searchEngineId) {\n\t\treturn { ok: false, reason: \"missing_api_key\", message: \"Provider google-cse requires searchEngineId.\" };\n\t}\n\n\tif ((config.provider === \"codex\" || config.provider === \"openai\") && !hasApiKey(config)) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\treason: \"missing_api_key\",\n\t\t\tmessage: `Provider ${config.provider} requires apiKey for hosted Responses API search.`,\n\t\t};\n\t}\n\n\tif (\n\t\tconfig.provider !== \"codex\" &&\n\t\tconfig.provider !== \"openai\" &&\n\t\tconfig.provider !== \"duckduckgo-html\" &&\n\t\t!hasApiKey(config)\n\t) {\n\t\treturn { ok: false, reason: \"missing_api_key\", message: `Provider ${config.provider} requires apiKey.` };\n\t}\n\n\treturn { ok: true, config };\n}\n\nexport function validateWebsearchConfig(\n\tconfig: WebsearchConfig,\n): ProviderValidationResult | { ok: true; config: WebsearchConfig } {\n\tif (!STRATEGIES.includes(config.strategy)) {\n\t\treturn { ok: false, reason: \"invalid_config\", message: `Unsupported routing strategy: ${config.strategy}` };\n\t}\n\tif (typeof config.auto !== \"boolean\") {\n\t\treturn { ok: false, reason: \"invalid_config\", message: \"Websearch config auto must be a boolean.\" };\n\t}\n\tif (config.providers.length === 0) {\n\t\treturn { ok: false, reason: \"invalid_config\", message: \"Websearch config requires at least one provider.\" };\n\t}\n\n\tfor (const provider of config.providers) {\n\t\tconst validation = validateProviderConfig(provider);\n\t\tif (!validation.ok) return validation;\n\t}\n\n\treturn { ok: true, config };\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport async function loadWebsearchConfig(options: ConfigLoadOptions): Promise<ConfigLoadResult> {\n\tconst home = options.homeDir ?? homedir();\n\tconst paths = [\n\t\tjoin(options.cwd, \".pi\", \"websearch.json\"),\n\t\tjoin(home, \"websearch.json\"),\n\t\tjoin(home, \".pi\", \"websearch.json\"),\n\t];\n\n\tfor (const path of paths) {\n\t\tif (!(await fileExists(path))) continue;\n\t\tconst raw = parseJsonObject(await readFile(path, \"utf8\"));\n\t\tif (!raw) {\n\t\t\treturn { ok: false, reason: \"invalid_config\", message: `Invalid JSON object in ${path}`, source: path };\n\t\t}\n\t\tconst config = configFromObject(raw);\n\t\tif (!config) {\n\t\t\treturn { ok: false, reason: \"invalid_config\", message: `Invalid provider config in ${path}`, source: path };\n\t\t}\n\t\tconst validation = validateWebsearchConfig(config);\n\t\tif (!validation.ok) return { ...validation, source: path };\n\t\treturn { ok: true, config, source: path };\n\t}\n\n\treturn { ok: true, config: DEFAULT_FREE_CONFIG, source: \"default:duckduckgo-html\" };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/config.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { CONFIG_DIR_NAME } from \"../../../../../config.ts\";\nimport { isAllowedProviderBaseUrl } from \"./provider-endpoints.ts\";\nimport type {\n\tCodexSearchMode,\n\tConfigLoadResult,\n\tJsonObject,\n\tJsonValue,\n\tProviderValidationResult,\n\tRoutingStrategy,\n\tSearchContextSize,\n\tSearchProvider,\n\tSearchProviderConfig,\n\tSearchProviderEntry,\n\tSearchUserLocation,\n\tWebsearchConfig,\n} from \"./types.ts\";\n\nconst PROVIDERS: readonly SearchProvider[] = [\n\t\"exa\",\n\t\"tavily\",\n\t\"brave\",\n\t\"duckduckgo-html\",\n\t\"serper\",\n\t\"google-cse\",\n\t\"z-ai\",\n\t\"openai\",\n\t\"codex\",\n\t\"anthropic\",\n\t\"perplexity\",\n\t\"xai\",\n\t\"kimi\",\n];\nconst CONTEXT_SIZES: readonly SearchContextSize[] = [\"low\", \"medium\", \"high\"];\nconst CODEX_MODES: readonly CodexSearchMode[] = [\"cached\", \"live\"];\nconst STRATEGIES: readonly RoutingStrategy[] = [\"priority\", \"round-robin\", \"fill-first\"];\nconst DEFAULT_FREE_CONFIG: WebsearchConfig = {\n\tstrategy: \"priority\",\n\tfallback: true,\n\tauto: true,\n\tproviders: [{ id: \"default\", provider: \"duckduckgo-html\", maxResults: 10 }],\n};\n\nexport interface ConfigLoadOptions {\n\tcwd: string;\n\thomeDir?: string;\n}\n\nfunction isJsonObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction oneOf<TValue extends string>(values: readonly TValue[], value: unknown): value is TValue {\n\treturn typeof value === \"string\" && (values as readonly string[]).includes(value);\n}\n\nfunction isStringArray(value: JsonValue | undefined): value is string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction optionalString(value: JsonValue | undefined): string | undefined {\n\treturn typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction optionalNumber(value: JsonValue | undefined): number | undefined {\n\treturn typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction optionalBoolean(value: JsonValue | undefined): boolean | undefined {\n\treturn typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction optionalProvider(value: JsonValue | undefined): SearchProvider | undefined {\n\treturn oneOf(PROVIDERS, value) ? value : undefined;\n}\n\nfunction optionalContextSize(value: JsonValue | undefined): SearchContextSize | undefined {\n\treturn oneOf(CONTEXT_SIZES, value) ? value : undefined;\n}\n\nfunction optionalCodexMode(value: JsonValue | undefined): CodexSearchMode | undefined {\n\treturn oneOf(CODEX_MODES, value) ? value : undefined;\n}\n\nfunction optionalStrategy(value: JsonValue | undefined): RoutingStrategy | undefined {\n\treturn oneOf(STRATEGIES, value) ? value : undefined;\n}\n\nfunction optionalLocation(value: JsonValue | undefined): SearchUserLocation | undefined {\n\tif (!isJsonObject(value)) return undefined;\n\tconst location: SearchUserLocation = {};\n\tconst country = optionalString(value.country);\n\tconst region = optionalString(value.region);\n\tconst city = optionalString(value.city);\n\tconst timezone = optionalString(value.timezone);\n\tif (country) location.country = country;\n\tif (region) location.region = region;\n\tif (city) location.city = city;\n\tif (timezone) location.timezone = timezone;\n\treturn Object.keys(location).length > 0 ? location : undefined;\n}\n\nfunction parseJsonObject(content: string): JsonObject | null {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(content);\n\t} catch {\n\t\treturn null;\n\t}\n\treturn isJsonObject(parsed) ? parsed : null;\n}\n\nfunction providerEntryFromObject(raw: JsonObject): SearchProviderEntry | null {\n\tconst provider = optionalProvider(raw.provider) ?? optionalProvider(raw.backend);\n\tif (!provider) return null;\n\n\tconst config: SearchProviderEntry = { provider };\n\tconst id = optionalString(raw.id);\n\tconst apiKey = optionalString(raw.apiKey);\n\tconst baseUrl = optionalString(raw.baseUrl);\n\tconst searchEngineId = optionalString(raw.searchEngineId);\n\tconst maxResults = optionalNumber(raw.maxResults);\n\tconst model = optionalString(raw.model);\n\tconst codexMode = optionalCodexMode(raw.codexMode);\n\tconst searchContextSize = optionalContextSize(raw.searchContextSize);\n\tconst rawAllowedDomains = raw.allowedDomains;\n\tconst rawBlockedDomains = raw.blockedDomains;\n\tconst allowedDomains = isStringArray(rawAllowedDomains) ? rawAllowedDomains : undefined;\n\tconst blockedDomains = isStringArray(rawBlockedDomains) ? rawBlockedDomains : undefined;\n\tconst userLocation = optionalLocation(raw.userLocation);\n\tconst timeoutMs = optionalNumber(raw.timeoutMs);\n\tconst priority = optionalNumber(raw.priority);\n\tconst weight = optionalNumber(raw.weight);\n\n\tif (id) config.id = id;\n\tif (apiKey) config.apiKey = apiKey;\n\tif (baseUrl) config.baseUrl = baseUrl;\n\tif (searchEngineId) config.searchEngineId = searchEngineId;\n\tif (maxResults) config.maxResults = maxResults;\n\tif (model) config.model = model;\n\tif (codexMode) config.codexMode = codexMode;\n\tif (searchContextSize) config.searchContextSize = searchContextSize;\n\tif (allowedDomains) config.allowedDomains = allowedDomains;\n\tif (blockedDomains) config.blockedDomains = blockedDomains;\n\tif (userLocation) config.userLocation = userLocation;\n\tif (timeoutMs !== undefined) config.timeoutMs = timeoutMs;\n\tif (priority !== undefined) config.priority = priority;\n\tif (weight !== undefined) config.weight = weight;\n\n\treturn config;\n}\n\nfunction configFromObject(raw: JsonObject): WebsearchConfig | null {\n\tconst auto = optionalBoolean(raw.auto) ?? true;\n\tconst providersValue = raw.providers;\n\tconst rawProviders = Array.isArray(providersValue) ? providersValue : undefined;\n\tif (rawProviders) {\n\t\tif (optionalProvider(raw.provider)) return null;\n\t\tconst providers = rawProviders\n\t\t\t.map((value) => (isJsonObject(value) ? providerEntryFromObject(value) : null))\n\t\t\t.filter((entry): entry is SearchProviderEntry => entry !== null);\n\t\tconst strategy = optionalStrategy(raw.strategy) ?? \"priority\";\n\t\tconst fallback = optionalBoolean(raw.fallback) ?? true;\n\t\treturn { strategy, fallback, auto, providers };\n\t}\n\n\tconst provider = providerEntryFromObject(raw);\n\treturn provider ? { strategy: \"priority\", fallback: true, auto, providers: [provider] } : null;\n}\n\nfunction hasApiKey(config: SearchProviderConfig): boolean {\n\treturn typeof config.apiKey === \"string\" && config.apiKey.length > 0;\n}\n\nexport function validateProviderConfig(config: SearchProviderEntry): ProviderValidationResult {\n\tif (!PROVIDERS.includes(config.provider)) {\n\t\treturn { ok: false, reason: \"invalid_config\", message: `Unsupported provider: ${config.provider}` };\n\t}\n\n\tif (config.allowedDomains && config.blockedDomains) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\treason: \"invalid_config\",\n\t\t\tmessage: \"Provider config cannot specify both allowedDomains and blockedDomains.\",\n\t\t};\n\t}\n\n\tif (config.weight !== undefined && config.weight <= 0) {\n\t\treturn { ok: false, reason: \"invalid_config\", message: \"Provider weight must be greater than 0.\" };\n\t}\n\n\tif (config.timeoutMs !== undefined && config.timeoutMs <= 0) {\n\t\treturn { ok: false, reason: \"invalid_config\", message: \"Provider timeoutMs must be greater than 0.\" };\n\t}\n\n\tif (config.baseUrl && !isAllowedProviderBaseUrl(config.baseUrl)) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\treason: \"invalid_config\",\n\t\t\tmessage: `Provider ${config.provider} baseUrl must be a public HTTPS URL without credentials.`,\n\t\t};\n\t}\n\n\tif (config.provider === \"google-cse\" && !config.searchEngineId) {\n\t\treturn { ok: false, reason: \"missing_api_key\", message: \"Provider google-cse requires searchEngineId.\" };\n\t}\n\n\tif ((config.provider === \"codex\" || config.provider === \"openai\") && !hasApiKey(config)) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\treason: \"missing_api_key\",\n\t\t\tmessage: `Provider ${config.provider} requires apiKey for hosted Responses API search.`,\n\t\t};\n\t}\n\n\tif (\n\t\tconfig.provider !== \"codex\" &&\n\t\tconfig.provider !== \"openai\" &&\n\t\tconfig.provider !== \"duckduckgo-html\" &&\n\t\t!hasApiKey(config)\n\t) {\n\t\treturn { ok: false, reason: \"missing_api_key\", message: `Provider ${config.provider} requires apiKey.` };\n\t}\n\n\treturn { ok: true, config };\n}\n\nexport function validateWebsearchConfig(\n\tconfig: WebsearchConfig,\n): ProviderValidationResult | { ok: true; config: WebsearchConfig } {\n\tif (!STRATEGIES.includes(config.strategy)) {\n\t\treturn { ok: false, reason: \"invalid_config\", message: `Unsupported routing strategy: ${config.strategy}` };\n\t}\n\tif (typeof config.auto !== \"boolean\") {\n\t\treturn { ok: false, reason: \"invalid_config\", message: \"Websearch config auto must be a boolean.\" };\n\t}\n\tif (config.providers.length === 0) {\n\t\treturn { ok: false, reason: \"invalid_config\", message: \"Websearch config requires at least one provider.\" };\n\t}\n\n\tfor (const provider of config.providers) {\n\t\tconst validation = validateProviderConfig(provider);\n\t\tif (!validation.ok) return validation;\n\t}\n\n\treturn { ok: true, config };\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport async function loadWebsearchConfig(options: ConfigLoadOptions): Promise<ConfigLoadResult> {\n\tconst home = options.homeDir ?? homedir();\n\tconst paths = [\n\t\tjoin(options.cwd, CONFIG_DIR_NAME, \"websearch.json\"),\n\t\tjoin(options.cwd, \".pi\", \"websearch.json\"),\n\t\tjoin(home, \"websearch.json\"),\n\t\tjoin(home, CONFIG_DIR_NAME, \"websearch.json\"),\n\t\tjoin(home, \".pi\", \"websearch.json\"),\n\t].filter((path, index, all) => all.indexOf(path) === index);\n\n\tfor (const path of paths) {\n\t\tif (!(await fileExists(path))) continue;\n\t\tconst raw = parseJsonObject(await readFile(path, \"utf8\"));\n\t\tif (!raw) {\n\t\t\treturn { ok: false, reason: \"invalid_config\", message: `Invalid JSON object in ${path}`, source: path };\n\t\t}\n\t\tconst config = configFromObject(raw);\n\t\tif (!config) {\n\t\t\treturn { ok: false, reason: \"invalid_config\", message: `Invalid provider config in ${path}`, source: path };\n\t\t}\n\t\tconst validation = validateWebsearchConfig(config);\n\t\tif (!validation.ok) return { ...validation, source: path };\n\t\treturn { ok: true, config, source: path };\n\t}\n\n\treturn { ok: true, config: DEFAULT_FREE_CONFIG, source: \"default:duckduckgo-html\" };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/native.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAkB,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,WAAW,eAAe;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,gBAAgB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC/D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhC,MAAM,WAAW,mBAAmB;IACnC,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvE,YAAY,CAAC,IAAI,eAAe,EAAE,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/native.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAkB,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,WAAW,eAAe;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,gBAAgB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC/D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhC,MAAM,WAAW,mBAAmB;IACnC,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvE,YAAY,CAAC,IAAI,eAAe,EAAE,CAAC;CACnC;AA+HD,wBAAsB,kBAAkB,CACvC,KAAK,EAAE,eAAe,GAAG,SAAS,EAClC,aAAa,EAAE,mBAAmB,GAAG,SAAS,EAC9C,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA6BhC;AAED,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,eAAe,GAAG,SAAS,EAClC,aAAa,EAAE,mBAAmB,GAAG,SAAS,EAC9C,EAAE,SAAW,GACX,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAErC"}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { isAllowedProviderBaseUrl } from "./provider-endpoints.js";
|
|
3
3
|
function nativeMapping(model) {
|
|
4
|
-
if (model.provider === "openai" &&
|
|
5
|
-
(/^(gpt-5\.5(-fast)?|gpt-4\.1(-mini)?)$/.test(model.id) || /^gpt-4o(-mini)?(-\d{4}-\d{2}-\d{2})?$/.test(model.id))) {
|
|
4
|
+
if (model.provider === "openai" && /^gpt-(4o|4\.1|5)/.test(model.id) && !model.id.includes("codex")) {
|
|
6
5
|
return { provider: "openai", resource: "responses" };
|
|
7
6
|
}
|
|
8
|
-
if (model.provider === "anthropic" &&
|
|
9
|
-
(/^claude-(opus|sonnet)-4(-\d+)?$/.test(model.id) || /^claude-(opus|sonnet)-4-\d+-\d{8}$/.test(model.id))) {
|
|
7
|
+
if (model.provider === "anthropic" && /^claude-/.test(model.id)) {
|
|
10
8
|
return { provider: "anthropic", resource: "messages" };
|
|
11
9
|
}
|
|
12
10
|
if (model.provider === "xai" && /^grok-/.test(model.id)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AA4BnE,SAAS,aAAa,CAAC,KAAsB;IAC5C,IACC,KAAK,CAAC,QAAQ,KAAK,QAAQ;QAC3B,CAAC,uCAAuC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,uCAAuC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EACjH,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IACtD,CAAC;IAED,IACC,KAAK,CAAC,QAAQ,KAAK,WAAW;QAC9B,CAAC,iCAAiC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,oCAAoC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EACxG,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IACxD,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;QACzD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IACnD,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,KAAK,YAAY,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;QAChE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IACjE,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,MAAM,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;QACvF,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC3D,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACjD,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,UAAU,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACjC,MAAM,iBAAiB,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;QACxD,MAAM,WAAW,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QACnD,IAAI,iBAAiB,KAAK,YAAY;YAAE,OAAO,IAAI,CAAC;QACpD,OAAO,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAe,EAAE,QAAgB;IAC1D,IAAI,UAAe,CAAC;IACpB,IAAI,CAAC;QACJ,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,OAAO,CAAC;IAChB,CAAC;IACD,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5D,MAAM,aAAa,GAAG,IAAI,QAAQ,EAAE,CAAC;IACrC,IAAI,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACzC,UAAU,CAAC,QAAQ,GAAG,WAAW,CAAC;IACnC,CAAC;SAAM,IAAI,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACxC,UAAU,CAAC,QAAQ,GAAG,GAAG,WAAW,GAAG,aAAa,EAAE,CAAC;IACxD,CAAC;SAAM,CAAC;QACP,UAAU,CAAC,QAAQ,GAAG,GAAG,WAAW,MAAM,aAAa,EAAE,CAAC;IAC3D,CAAC;IACD,UAAU,CAAC,IAAI,GAAG,EAAE,CAAC;IACrB,OAAO,UAAU,CAAC,IAAI,CAAC;AACxB,CAAC;AAED,SAAS,cAAc,CAAC,KAAsB;IAC7C,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClE,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAClC,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACzD,OAAO,GAAG,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,uBAAuB,CAAC,QAAwB,EAAE,QAAgB;IAC1E,MAAM,gBAAgB,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1F,OAAO,UAAU,QAAQ,IAAI,gBAAgB,EAAE,CAAC;AACjD,CAAC;AAED,KAAK,UAAU,wBAAwB,CACtC,KAAkC,EAClC,aAA8C,EAC9C,OAAO,GAAuB,EAAE;IAEhC,IAAI,CAAC,KAAK,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,EAAE,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAE1C,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClE,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpD,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,MAAM,WAAW,GAAG,aAAa,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC7D,IAAI,IAAsB,CAAC;IAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,IAAI,GAAG,MAAM,WAAW,CAAC;IAC1B,CAAC;SAAM,CAAC;QACP,MAAM,CAAC,cAAc,EAAE,CAAC;QACxB,IAAI,mBAAmB,GAAG,GAAS,EAAE,GAAE,CAAC,CAAC;QACzC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;YAC5D,MAAM,OAAO,GAAG,GAAS,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAClD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1D,mBAAmB,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;QACH,IAAI,CAAC;YACJ,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;QACxD,CAAC;gBAAS,CAAC;YACV,mBAAmB,EAAE,CAAC;QACvB,CAAC;IACF,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAE1C,OAAO;QACN,EAAE;QACF,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO;QACP,KAAK,EAAE,KAAK,CAAC,EAAE;QACf,QAAQ,EAAE,CAAC,CAAC;KACZ,CAAC;AACH,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACvC,KAAkC,EAClC,aAA8C,EAC9C,MAAoB;IAEpB,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAE9B,MAAM,OAAO,GAA0B,EAAE,CAAC;IAC1C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IAErC,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5D,IAAI,cAAc,EAAE,CAAC;QACpB,UAAU,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC/B,MAAM,WAAW,GAAG,MAAM,wBAAwB,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACrF,IAAI,WAAW;YAAE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,CAAC,aAAa,CAAC,YAAY;QAAE,OAAO,OAAO,CAAC;IAEhD,KAAK,MAAM,cAAc,IAAI,aAAa,CAAC,YAAY,EAAE,EAAE,CAAC;QAC3D,MAAM,QAAQ,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;QAChD,IAAI,CAAC,QAAQ,IAAI,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS;QACpD,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzB,MAAM,KAAK,GAAG,MAAM,wBAAwB,CAAC,cAAc,EAAE,aAAa,EAAE;YAC3E,EAAE,EAAE,mBAAmB;YACvB,MAAM;SACN,CAAC,CAAC;QACH,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,uBAAuB,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,KAAkC,EAClC,aAA8C,EAC9C,EAAE,GAAG,QAAQ;IAEb,OAAO,wBAAwB,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AAC/D,CAAC","sourcesContent":["import { createHash } from \"node:crypto\";\n\nimport { isAllowedProviderBaseUrl } from \"./provider-endpoints.ts\";\nimport type { SearchProvider, SearchProviderEntry } from \"./types.ts\";\n\nexport interface NativeModelInfo {\n\tprovider: string;\n\tid: string;\n\tbaseUrl: string;\n}\n\nexport type NativeAuthResult =\n\t| { ok: true; apiKey?: string; headers?: Record<string, string> }\n\t| { ok: false; error: string };\n\nexport interface NativeModelRegistry {\n\tgetApiKeyAndHeaders(model: NativeModelInfo): Promise<NativeAuthResult>;\n\tgetAvailable?(): NativeModelInfo[];\n}\n\ninterface NativeProviderMapping {\n\tprovider: SearchProvider;\n\tresource: string;\n}\n\ninterface NativeEntryOptions {\n\tid?: string;\n\tsignal?: AbortSignal;\n}\n\nfunction nativeMapping(model: NativeModelInfo): NativeProviderMapping | null {\n\tif (\n\t\tmodel.provider === \"openai\" &&\n\t\t(/^(gpt-5\\.5(-fast)?|gpt-4\\.1(-mini)?)$/.test(model.id) || /^gpt-4o(-mini)?(-\\d{4}-\\d{2}-\\d{2})?$/.test(model.id))\n\t) {\n\t\treturn { provider: \"openai\", resource: \"responses\" };\n\t}\n\n\tif (\n\t\tmodel.provider === \"anthropic\" &&\n\t\t(/^claude-(opus|sonnet)-4(-\\d+)?$/.test(model.id) || /^claude-(opus|sonnet)-4-\\d+-\\d{8}$/.test(model.id))\n\t) {\n\t\treturn { provider: \"anthropic\", resource: \"messages\" };\n\t}\n\n\tif (model.provider === \"xai\" && /^grok-/.test(model.id)) {\n\t\treturn { provider: \"xai\", resource: \"responses\" };\n\t}\n\n\tif (model.provider === \"perplexity\" && /^sonar/.test(model.id)) {\n\t\treturn { provider: \"perplexity\", resource: \"chat/completions\" };\n\t}\n\n\tif ((model.provider === \"z-ai\" || model.provider === \"zai\") && /^glm-/.test(model.id)) {\n\t\treturn { provider: \"z-ai\", resource: \"chat/completions\" };\n\t}\n\n\tif (model.provider === \"kimi-coding\") {\n\t\treturn { provider: \"kimi\", resource: \"search\" };\n\t}\n\n\tif (model.provider === \"openrouter\") {\n\t\tconst slashIndex = model.id.indexOf(\"/\");\n\t\tif (slashIndex <= 0) return null;\n\t\tconst effectiveProvider = model.id.slice(0, slashIndex);\n\t\tconst effectiveId = model.id.slice(slashIndex + 1);\n\t\tif (effectiveProvider === \"openrouter\") return null;\n\t\treturn nativeMapping({ ...model, provider: effectiveProvider, id: effectiveId });\n\t}\n\n\treturn null;\n}\n\nfunction buildEndpointUrl(baseUrl: string, resource: string): string {\n\tlet configured: URL;\n\ttry {\n\t\tconfigured = new URL(baseUrl);\n\t} catch {\n\t\treturn baseUrl;\n\t}\n\tconst trimmedPath = configured.pathname.replace(/\\/+$/, \"\");\n\tconst resourceSlash = `/${resource}`;\n\tif (trimmedPath.endsWith(resourceSlash)) {\n\t\tconfigured.pathname = trimmedPath;\n\t} else if (/\\/v\\d+$/.test(trimmedPath)) {\n\t\tconfigured.pathname = `${trimmedPath}${resourceSlash}`;\n\t} else {\n\t\tconfigured.pathname = `${trimmedPath}/v1${resourceSlash}`;\n\t}\n\tconfigured.hash = \"\";\n\treturn configured.href;\n}\n\nfunction nativeRouteKey(model: NativeModelInfo): string | null {\n\tconst mapping = nativeMapping(model);\n\tif (!mapping) return null;\n\tconst baseUrl = buildEndpointUrl(model.baseUrl, mapping.resource);\n\tif (!isAllowedProviderBaseUrl(baseUrl)) return null;\n\tconst routeUrl = new URL(baseUrl);\n\trouteUrl.hostname = routeUrl.hostname.replace(/\\.$/, \"\");\n\treturn `${mapping.provider}|${routeUrl.href}`;\n}\n\nfunction discoveredNativeEntryId(provider: SearchProvider, routeKey: string): string {\n\tconst routeFingerprint = createHash(\"sha256\").update(routeKey).digest(\"hex\").slice(0, 16);\n\treturn `native-${provider}-${routeFingerprint}`;\n}\n\nasync function buildNativeEntryForModel(\n\tmodel: NativeModelInfo | undefined,\n\tmodelRegistry: NativeModelRegistry | undefined,\n\toptions: NativeEntryOptions = {},\n): Promise<SearchProviderEntry | null> {\n\tif (!model || !modelRegistry) return null;\n\tconst { id = \"native\", signal } = options;\n\n\tconst mapping = nativeMapping(model);\n\tif (!mapping) return null;\n\tconst baseUrl = buildEndpointUrl(model.baseUrl, mapping.resource);\n\tif (!isAllowedProviderBaseUrl(baseUrl)) return null;\n\n\tsignal?.throwIfAborted();\n\tconst authPromise = modelRegistry.getApiKeyAndHeaders(model);\n\tlet auth: NativeAuthResult;\n\tif (!signal) {\n\t\tauth = await authPromise;\n\t} else {\n\t\tsignal.throwIfAborted();\n\t\tlet removeAbortListener = (): void => {};\n\t\tconst abortPromise = new Promise<never>((_resolve, reject) => {\n\t\t\tconst onAbort = (): void => reject(signal.reason);\n\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\tremoveAbortListener = () => signal.removeEventListener(\"abort\", onAbort);\n\t\t});\n\t\ttry {\n\t\t\tauth = await Promise.race([authPromise, abortPromise]);\n\t\t} finally {\n\t\t\tremoveAbortListener();\n\t\t}\n\t}\n\tif (!auth.ok || !auth.apiKey) return null;\n\n\treturn {\n\t\tid,\n\t\tprovider: mapping.provider,\n\t\tapiKey: auth.apiKey,\n\t\tbaseUrl,\n\t\tmodel: model.id,\n\t\tpriority: -1,\n\t};\n}\nexport async function buildNativeEntries(\n\tmodel: NativeModelInfo | undefined,\n\tmodelRegistry: NativeModelRegistry | undefined,\n\tsignal?: AbortSignal,\n): Promise<SearchProviderEntry[]> {\n\tsignal?.throwIfAborted();\n\tif (!modelRegistry) return [];\n\n\tconst entries: SearchProviderEntry[] = [];\n\tconst seenRoutes = new Set<string>();\n\n\tconst activeRouteKey = model ? nativeRouteKey(model) : null;\n\tif (activeRouteKey) {\n\t\tseenRoutes.add(activeRouteKey);\n\t\tconst activeEntry = await buildNativeEntryForModel(model, modelRegistry, { signal });\n\t\tif (activeEntry) entries.push(activeEntry);\n\t}\n\n\tif (!modelRegistry.getAvailable) return entries;\n\n\tfor (const availableModel of modelRegistry.getAvailable()) {\n\t\tconst routeKey = nativeRouteKey(availableModel);\n\t\tif (!routeKey || seenRoutes.has(routeKey)) continue;\n\t\tseenRoutes.add(routeKey);\n\t\tconst entry = await buildNativeEntryForModel(availableModel, modelRegistry, {\n\t\t\tid: \"native-discovered\",\n\t\t\tsignal,\n\t\t});\n\t\tif (!entry) continue;\n\t\tentries.push({ ...entry, id: discoveredNativeEntryId(entry.provider, routeKey) });\n\t}\n\n\treturn entries;\n}\n\nexport async function buildNativeEntry(\n\tmodel: NativeModelInfo | undefined,\n\tmodelRegistry: NativeModelRegistry | undefined,\n\tid = \"native\",\n): Promise<SearchProviderEntry | null> {\n\treturn buildNativeEntryForModel(model, modelRegistry, { id });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"native.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/native.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\n\nimport { isAllowedProviderBaseUrl } from \"./provider-endpoints.ts\";\nimport type { SearchProvider, SearchProviderEntry } from \"./types.ts\";\n\nexport interface NativeModelInfo {\n\tprovider: string;\n\tid: string;\n\tbaseUrl: string;\n}\n\nexport type NativeAuthResult =\n\t| { ok: true; apiKey?: string; headers?: Record<string, string> }\n\t| { ok: false; error: string };\n\nexport interface NativeModelRegistry {\n\tgetApiKeyAndHeaders(model: NativeModelInfo): Promise<NativeAuthResult>;\n\tgetAvailable?(): NativeModelInfo[];\n}\n\ninterface NativeProviderMapping {\n\tprovider: SearchProvider;\n\tresource: string;\n}\n\ninterface NativeEntryOptions {\n\tid?: string;\n\tsignal?: AbortSignal;\n}\n\nfunction nativeMapping(model: NativeModelInfo): NativeProviderMapping | null {\n\tif (model.provider === \"openai\" && /^gpt-(4o|4\\.1|5)/.test(model.id) && !model.id.includes(\"codex\")) {\n\t\treturn { provider: \"openai\", resource: \"responses\" };\n\t}\n\n\tif (model.provider === \"anthropic\" && /^claude-/.test(model.id)) {\n\t\treturn { provider: \"anthropic\", resource: \"messages\" };\n\t}\n\n\tif (model.provider === \"xai\" && /^grok-/.test(model.id)) {\n\t\treturn { provider: \"xai\", resource: \"responses\" };\n\t}\n\n\tif (model.provider === \"perplexity\" && /^sonar/.test(model.id)) {\n\t\treturn { provider: \"perplexity\", resource: \"chat/completions\" };\n\t}\n\n\tif ((model.provider === \"z-ai\" || model.provider === \"zai\") && /^glm-/.test(model.id)) {\n\t\treturn { provider: \"z-ai\", resource: \"chat/completions\" };\n\t}\n\n\tif (model.provider === \"kimi-coding\") {\n\t\treturn { provider: \"kimi\", resource: \"search\" };\n\t}\n\n\tif (model.provider === \"openrouter\") {\n\t\tconst slashIndex = model.id.indexOf(\"/\");\n\t\tif (slashIndex <= 0) return null;\n\t\tconst effectiveProvider = model.id.slice(0, slashIndex);\n\t\tconst effectiveId = model.id.slice(slashIndex + 1);\n\t\tif (effectiveProvider === \"openrouter\") return null;\n\t\treturn nativeMapping({ ...model, provider: effectiveProvider, id: effectiveId });\n\t}\n\n\treturn null;\n}\n\nfunction buildEndpointUrl(baseUrl: string, resource: string): string {\n\tlet configured: URL;\n\ttry {\n\t\tconfigured = new URL(baseUrl);\n\t} catch {\n\t\treturn baseUrl;\n\t}\n\tconst trimmedPath = configured.pathname.replace(/\\/+$/, \"\");\n\tconst resourceSlash = `/${resource}`;\n\tif (trimmedPath.endsWith(resourceSlash)) {\n\t\tconfigured.pathname = trimmedPath;\n\t} else if (/\\/v\\d+$/.test(trimmedPath)) {\n\t\tconfigured.pathname = `${trimmedPath}${resourceSlash}`;\n\t} else {\n\t\tconfigured.pathname = `${trimmedPath}/v1${resourceSlash}`;\n\t}\n\tconfigured.hash = \"\";\n\treturn configured.href;\n}\n\nfunction nativeRouteKey(model: NativeModelInfo): string | null {\n\tconst mapping = nativeMapping(model);\n\tif (!mapping) return null;\n\tconst baseUrl = buildEndpointUrl(model.baseUrl, mapping.resource);\n\tif (!isAllowedProviderBaseUrl(baseUrl)) return null;\n\tconst routeUrl = new URL(baseUrl);\n\trouteUrl.hostname = routeUrl.hostname.replace(/\\.$/, \"\");\n\treturn `${mapping.provider}|${routeUrl.href}`;\n}\n\nfunction discoveredNativeEntryId(provider: SearchProvider, routeKey: string): string {\n\tconst routeFingerprint = createHash(\"sha256\").update(routeKey).digest(\"hex\").slice(0, 16);\n\treturn `native-${provider}-${routeFingerprint}`;\n}\n\nasync function buildNativeEntryForModel(\n\tmodel: NativeModelInfo | undefined,\n\tmodelRegistry: NativeModelRegistry | undefined,\n\toptions: NativeEntryOptions = {},\n): Promise<SearchProviderEntry | null> {\n\tif (!model || !modelRegistry) return null;\n\tconst { id = \"native\", signal } = options;\n\n\tconst mapping = nativeMapping(model);\n\tif (!mapping) return null;\n\tconst baseUrl = buildEndpointUrl(model.baseUrl, mapping.resource);\n\tif (!isAllowedProviderBaseUrl(baseUrl)) return null;\n\n\tsignal?.throwIfAborted();\n\tconst authPromise = modelRegistry.getApiKeyAndHeaders(model);\n\tlet auth: NativeAuthResult;\n\tif (!signal) {\n\t\tauth = await authPromise;\n\t} else {\n\t\tsignal.throwIfAborted();\n\t\tlet removeAbortListener = (): void => {};\n\t\tconst abortPromise = new Promise<never>((_resolve, reject) => {\n\t\t\tconst onAbort = (): void => reject(signal.reason);\n\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\tremoveAbortListener = () => signal.removeEventListener(\"abort\", onAbort);\n\t\t});\n\t\ttry {\n\t\t\tauth = await Promise.race([authPromise, abortPromise]);\n\t\t} finally {\n\t\t\tremoveAbortListener();\n\t\t}\n\t}\n\tif (!auth.ok || !auth.apiKey) return null;\n\n\treturn {\n\t\tid,\n\t\tprovider: mapping.provider,\n\t\tapiKey: auth.apiKey,\n\t\tbaseUrl,\n\t\tmodel: model.id,\n\t\tpriority: -1,\n\t};\n}\nexport async function buildNativeEntries(\n\tmodel: NativeModelInfo | undefined,\n\tmodelRegistry: NativeModelRegistry | undefined,\n\tsignal?: AbortSignal,\n): Promise<SearchProviderEntry[]> {\n\tsignal?.throwIfAborted();\n\tif (!modelRegistry) return [];\n\n\tconst entries: SearchProviderEntry[] = [];\n\tconst seenRoutes = new Set<string>();\n\n\tconst activeRouteKey = model ? nativeRouteKey(model) : null;\n\tif (activeRouteKey) {\n\t\tseenRoutes.add(activeRouteKey);\n\t\tconst activeEntry = await buildNativeEntryForModel(model, modelRegistry, { signal });\n\t\tif (activeEntry) entries.push(activeEntry);\n\t}\n\n\tif (!modelRegistry.getAvailable) return entries;\n\n\tfor (const availableModel of modelRegistry.getAvailable()) {\n\t\tconst routeKey = nativeRouteKey(availableModel);\n\t\tif (!routeKey || seenRoutes.has(routeKey)) continue;\n\t\tseenRoutes.add(routeKey);\n\t\tconst entry = await buildNativeEntryForModel(availableModel, modelRegistry, {\n\t\t\tid: \"native-discovered\",\n\t\t\tsignal,\n\t\t});\n\t\tif (!entry) continue;\n\t\tentries.push({ ...entry, id: discoveredNativeEntryId(entry.provider, routeKey) });\n\t}\n\n\treturn entries;\n}\n\nexport async function buildNativeEntry(\n\tmodel: NativeModelInfo | undefined,\n\tmodelRegistry: NativeModelRegistry | undefined,\n\tid = \"native\",\n): Promise<SearchProviderEntry | null> {\n\treturn buildNativeEntryForModel(model, modelRegistry, { id });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderers.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/renderers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"renderers.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/renderers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAG9C,OAAO,KAAK,EAA4D,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEhH,UAAU,SAAS;IAClB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACvC;AAED,UAAU,UAAU;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,UAAU,UAAU,CAAC,QAAQ;IAC5B,OAAO,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,OAAO,CAAC,EAAE,QAAQ,CAAC;CACnB;AAED,UAAU,mBAAmB;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAuCD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAMzE;AAED,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,UAAU,CAAC,mBAAmB,CAAC,EACvC,OAAO,EAAE,mBAAmB,EAC5B,KAAK,EAAE,SAAS,GACd,IAAI,CAoDN"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Text } from "@earendil-works/pi-tui";
|
|
2
|
+
import { providerEntryLabel } from "./search.js";
|
|
2
3
|
function shorten(value, max) {
|
|
3
4
|
return value.length <= max ? value : `${value.slice(0, max - 1)}…`;
|
|
4
5
|
}
|
|
@@ -8,10 +9,24 @@ function durationText(durationMs) {
|
|
|
8
9
|
function attemptLabel(attempts) {
|
|
9
10
|
return attempts
|
|
10
11
|
? attempts
|
|
11
|
-
.map((attempt) => `${attempt
|
|
12
|
+
.map((attempt) => `${providerEntryLabel(attempt)}:${attempt.error ? "failed" : attempt.resultsCount}`)
|
|
12
13
|
.join(" -> ")
|
|
13
14
|
: "";
|
|
14
15
|
}
|
|
16
|
+
function routeStateLabel(details) {
|
|
17
|
+
const labels = details.routeLabels ?? details.providerLabels;
|
|
18
|
+
if (labels.length === 0)
|
|
19
|
+
return "";
|
|
20
|
+
const attempts = details.attempts ?? [];
|
|
21
|
+
return labels
|
|
22
|
+
.map((label, index) => {
|
|
23
|
+
const attempt = attempts[index];
|
|
24
|
+
if (attempt)
|
|
25
|
+
return `${label}:${attempt.error ? "failed" : attempt.resultsCount}`;
|
|
26
|
+
return `${label}:${index === attempts.length ? "searching" : "pending"}`;
|
|
27
|
+
})
|
|
28
|
+
.join(" -> ");
|
|
29
|
+
}
|
|
15
30
|
function isSearchProgressDetails(details) {
|
|
16
31
|
return details !== undefined && "phase" in details && details.phase === "searching";
|
|
17
32
|
}
|
|
@@ -30,12 +45,9 @@ export function renderSearchResult(result, options, theme) {
|
|
|
30
45
|
const details = result.details;
|
|
31
46
|
if (isSearchProgressDetails(details)) {
|
|
32
47
|
if (details.currentProvider) {
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const line = theme.fg("warning", `Searching "${shorten(details.query, 80)}" via ${details.currentProvider}${step} (max ${details.maxResults})`);
|
|
37
|
-
const attempts = attemptLabel(details.attempts);
|
|
38
|
-
const rows = options.expanded && attempts ? [line, theme.fg("muted", `route ${attempts}`)] : [line];
|
|
48
|
+
const line = theme.fg("warning", `Searching "${shorten(details.query, 80)}" via ${details.currentProvider} (max ${details.maxResults})`);
|
|
49
|
+
const route = routeStateLabel(details);
|
|
50
|
+
const rows = options.expanded && route ? [line, theme.fg("muted", `route ${route}`)] : [line];
|
|
39
51
|
return new Text(rows.join("\n"), 0, 0);
|
|
40
52
|
}
|
|
41
53
|
const route = details.providerLabels.length > 0 ? details.providerLabels.join(" -> ") : "configured providers";
|
|
@@ -53,7 +65,7 @@ export function renderSearchResult(result, options, theme) {
|
|
|
53
65
|
if (details.error)
|
|
54
66
|
return new Text(theme.fg("error", details.error), 0, 0);
|
|
55
67
|
const count = details.results.length;
|
|
56
|
-
const provider = details
|
|
68
|
+
const provider = providerEntryLabel(details);
|
|
57
69
|
const summary = theme.fg("success", `${count} result${count === 1 ? "" : "s"}`) +
|
|
58
70
|
theme.fg("muted", ` via ${provider}${details.strategy ? ` (${details.strategy})` : ""} in ${durationText(details.durationMs)}`) +
|
|
59
71
|
(details.truncated ? theme.fg("warning", " (truncated)") : "");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderers.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/renderers.ts"],"names":[],"mappings":"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","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\n\nimport type { SearchDetails, SearchErrorDetails, SearchProgressDetails, SearchRenderDetails } from \"./types.ts\";\n\ninterface ThemeLike {\n\tbold(value: string): string;\n\tfg(key: string, value: string): string;\n}\n\ninterface SearchArgs {\n\tquery: string;\n\tallowed_domains?: string[];\n\tblocked_domains?: string[];\n}\n\ninterface ResultLike<TDetails> {\n\tcontent: ReadonlyArray<{ type: string; text?: string }>;\n\tdetails?: TDetails;\n}\n\ninterface RenderResultOptions {\n\texpanded?: boolean;\n\tisPartial?: boolean;\n}\n\nfunction shorten(value: string, max: number): string {\n\treturn value.length <= max ? value : `${value.slice(0, max - 1)}…`;\n}\n\nfunction durationText(durationMs: number): string {\n\treturn durationMs >= 1000 ? `${Math.round(durationMs / 1000)}s` : `${durationMs}ms`;\n}\n\nfunction attemptLabel(attempts: SearchDetails[\"attempts\"]): string {\n\treturn attempts\n\t\t? attempts\n\t\t\t\t.map(\n\t\t\t\t\t(attempt) =>\n\t\t\t\t\t\t`${attempt.entryId ? `${attempt.provider}/${attempt.entryId}` : attempt.provider}:${attempt.error ? \"failed\" : attempt.resultsCount}`,\n\t\t\t\t)\n\t\t\t\t.join(\" -> \")\n\t\t: \"\";\n}\n\nfunction isSearchProgressDetails(details: SearchRenderDetails | undefined): details is SearchProgressDetails {\n\treturn details !== undefined && \"phase\" in details && details.phase === \"searching\";\n}\n\nfunction isSearchErrorDetails(details: SearchRenderDetails): details is SearchErrorDetails {\n\treturn \"phase\" in details && details.phase === \"error\";\n}\n\nexport function renderSearchCall(args: SearchArgs, theme: ThemeLike): Text {\n\tconst head = theme.fg(\"toolTitle\", theme.bold(\"web_search \"));\n\tconst query = theme.fg(\"accent\", `\"${shorten(args.query, 90)}\"`);\n\tconst domains = args.allowed_domains ?? args.blocked_domains;\n\tconst filter = domains?.length ? theme.fg(\"muted\", ` domains:${domains.length}`) : \"\";\n\treturn new Text(head + query + filter, 0, 0);\n}\n\nexport function renderSearchResult(\n\tresult: ResultLike<SearchRenderDetails>,\n\toptions: RenderResultOptions,\n\ttheme: ThemeLike,\n): Text {\n\tif (options.isPartial) {\n\t\tconst details = result.details;\n\t\tif (isSearchProgressDetails(details)) {\n\t\t\tif (details.currentProvider) {\n\t\t\t\tconst total = details.providerLabels.length;\n\t\t\t\tconst position = Math.min((details.attempts?.length ?? 0) + 1, Math.max(total, 1));\n\t\t\t\tconst step = total > 1 ? ` [${position}/${total}]` : \"\";\n\t\t\t\tconst line = theme.fg(\n\t\t\t\t\t\"warning\",\n\t\t\t\t\t`Searching \"${shorten(details.query, 80)}\" via ${details.currentProvider}${step} (max ${details.maxResults})`,\n\t\t\t\t);\n\t\t\t\tconst attempts = attemptLabel(details.attempts);\n\t\t\t\tconst rows = options.expanded && attempts ? [line, theme.fg(\"muted\", `route ${attempts}`)] : [line];\n\t\t\t\treturn new Text(rows.join(\"\\n\"), 0, 0);\n\t\t\t}\n\t\t\tconst route = details.providerLabels.length > 0 ? details.providerLabels.join(\" -> \") : \"configured providers\";\n\t\t\treturn new Text(\n\t\t\t\ttheme.fg(\"warning\", `Searching \"${shorten(details.query, 80)}\" via ${route} (max ${details.maxResults})`),\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t}\n\t\treturn new Text(theme.fg(\"warning\", result.content[0]?.text ?? \"Searching the web...\"), 0, 0);\n\t}\n\n\tconst details = result.details;\n\tif (!details) return new Text(theme.fg(\"muted\", result.content[0]?.text ?? \"\"), 0, 0);\n\tif (isSearchProgressDetails(details)) return new Text(theme.fg(\"muted\", result.content[0]?.text ?? \"\"), 0, 0);\n\tif (isSearchErrorDetails(details)) return new Text(theme.fg(\"error\", details.error), 0, 0);\n\tif (details.error) return new Text(theme.fg(\"error\", details.error), 0, 0);\n\n\tconst count = details.results.length;\n\tconst provider = details.entryId ? `${details.provider}/${details.entryId}` : details.provider;\n\tconst summary =\n\t\ttheme.fg(\"success\", `${count} result${count === 1 ? \"\" : \"s\"}`) +\n\t\ttheme.fg(\n\t\t\t\"muted\",\n\t\t\t` via ${provider}${details.strategy ? ` (${details.strategy})` : \"\"} in ${durationText(details.durationMs)}`,\n\t\t) +\n\t\t(details.truncated ? theme.fg(\"warning\", \" (truncated)\") : \"\");\n\n\tif (count === 0) return new Text(summary, 0, 0);\n\n\tconst attempts = attemptLabel(details.attempts);\n\tconst rows = options.expanded && attempts ? [summary, theme.fg(\"muted\", `route ${attempts}`)] : [summary];\n\tconst visibleLimit = options.expanded ? 8 : 3;\n\tfor (const item of details.results.slice(0, visibleLimit)) {\n\t\trows.push(`${theme.fg(\"accent\", shorten(item.title, 80))} ${theme.fg(\"dim\", shorten(item.url, 100))}`);\n\t\tif (item.snippet) rows.push(theme.fg(\"muted\", ` ${shorten(item.snippet, 140)}`));\n\t}\n\tif (details.results.length > visibleLimit) {\n\t\trows.push(theme.fg(\"dim\", `… ${details.results.length - visibleLimit} more sources`));\n\t}\n\treturn new Text(rows.join(\"\\n\"), 0, 0);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"renderers.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/renderers.ts"],"names":[],"mappings":"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","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\n\nimport { providerEntryLabel } from \"./search.ts\";\nimport type { SearchDetails, SearchErrorDetails, SearchProgressDetails, SearchRenderDetails } from \"./types.ts\";\n\ninterface ThemeLike {\n\tbold(value: string): string;\n\tfg(key: string, value: string): string;\n}\n\ninterface SearchArgs {\n\tquery: string;\n\tallowed_domains?: string[];\n\tblocked_domains?: string[];\n}\n\ninterface ResultLike<TDetails> {\n\tcontent: ReadonlyArray<{ type: string; text?: string }>;\n\tdetails?: TDetails;\n}\n\ninterface RenderResultOptions {\n\texpanded?: boolean;\n\tisPartial?: boolean;\n}\n\nfunction shorten(value: string, max: number): string {\n\treturn value.length <= max ? value : `${value.slice(0, max - 1)}…`;\n}\n\nfunction durationText(durationMs: number): string {\n\treturn durationMs >= 1000 ? `${Math.round(durationMs / 1000)}s` : `${durationMs}ms`;\n}\n\nfunction attemptLabel(attempts: SearchDetails[\"attempts\"]): string {\n\treturn attempts\n\t\t? attempts\n\t\t\t\t.map((attempt) => `${providerEntryLabel(attempt)}:${attempt.error ? \"failed\" : attempt.resultsCount}`)\n\t\t\t\t.join(\" -> \")\n\t\t: \"\";\n}\n\nfunction routeStateLabel(details: SearchProgressDetails): string {\n\tconst labels = details.routeLabels ?? details.providerLabels;\n\tif (labels.length === 0) return \"\";\n\tconst attempts = details.attempts ?? [];\n\treturn labels\n\t\t.map((label, index) => {\n\t\t\tconst attempt = attempts[index];\n\t\t\tif (attempt) return `${label}:${attempt.error ? \"failed\" : attempt.resultsCount}`;\n\t\t\treturn `${label}:${index === attempts.length ? \"searching\" : \"pending\"}`;\n\t\t})\n\t\t.join(\" -> \");\n}\n\nfunction isSearchProgressDetails(details: SearchRenderDetails | undefined): details is SearchProgressDetails {\n\treturn details !== undefined && \"phase\" in details && details.phase === \"searching\";\n}\n\nfunction isSearchErrorDetails(details: SearchRenderDetails): details is SearchErrorDetails {\n\treturn \"phase\" in details && details.phase === \"error\";\n}\n\nexport function renderSearchCall(args: SearchArgs, theme: ThemeLike): Text {\n\tconst head = theme.fg(\"toolTitle\", theme.bold(\"web_search \"));\n\tconst query = theme.fg(\"accent\", `\"${shorten(args.query, 90)}\"`);\n\tconst domains = args.allowed_domains ?? args.blocked_domains;\n\tconst filter = domains?.length ? theme.fg(\"muted\", ` domains:${domains.length}`) : \"\";\n\treturn new Text(head + query + filter, 0, 0);\n}\n\nexport function renderSearchResult(\n\tresult: ResultLike<SearchRenderDetails>,\n\toptions: RenderResultOptions,\n\ttheme: ThemeLike,\n): Text {\n\tif (options.isPartial) {\n\t\tconst details = result.details;\n\t\tif (isSearchProgressDetails(details)) {\n\t\t\tif (details.currentProvider) {\n\t\t\t\tconst line = theme.fg(\n\t\t\t\t\t\"warning\",\n\t\t\t\t\t`Searching \"${shorten(details.query, 80)}\" via ${details.currentProvider} (max ${details.maxResults})`,\n\t\t\t\t);\n\t\t\t\tconst route = routeStateLabel(details);\n\t\t\t\tconst rows = options.expanded && route ? [line, theme.fg(\"muted\", `route ${route}`)] : [line];\n\t\t\t\treturn new Text(rows.join(\"\\n\"), 0, 0);\n\t\t\t}\n\t\t\tconst route = details.providerLabels.length > 0 ? details.providerLabels.join(\" -> \") : \"configured providers\";\n\t\t\treturn new Text(\n\t\t\t\ttheme.fg(\"warning\", `Searching \"${shorten(details.query, 80)}\" via ${route} (max ${details.maxResults})`),\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t}\n\t\treturn new Text(theme.fg(\"warning\", result.content[0]?.text ?? \"Searching the web...\"), 0, 0);\n\t}\n\n\tconst details = result.details;\n\tif (!details) return new Text(theme.fg(\"muted\", result.content[0]?.text ?? \"\"), 0, 0);\n\tif (isSearchProgressDetails(details)) return new Text(theme.fg(\"muted\", result.content[0]?.text ?? \"\"), 0, 0);\n\tif (isSearchErrorDetails(details)) return new Text(theme.fg(\"error\", details.error), 0, 0);\n\tif (details.error) return new Text(theme.fg(\"error\", details.error), 0, 0);\n\n\tconst count = details.results.length;\n\tconst provider = providerEntryLabel(details);\n\tconst summary =\n\t\ttheme.fg(\"success\", `${count} result${count === 1 ? \"\" : \"s\"}`) +\n\t\ttheme.fg(\n\t\t\t\"muted\",\n\t\t\t` via ${provider}${details.strategy ? ` (${details.strategy})` : \"\"} in ${durationText(details.durationMs)}`,\n\t\t) +\n\t\t(details.truncated ? theme.fg(\"warning\", \" (truncated)\") : \"\");\n\n\tif (count === 0) return new Text(summary, 0, 0);\n\n\tconst attempts = attemptLabel(details.attempts);\n\tconst rows = options.expanded && attempts ? [summary, theme.fg(\"muted\", `route ${attempts}`)] : [summary];\n\tconst visibleLimit = options.expanded ? 8 : 3;\n\tfor (const item of details.results.slice(0, visibleLimit)) {\n\t\trows.push(`${theme.fg(\"accent\", shorten(item.title, 80))} ${theme.fg(\"dim\", shorten(item.url, 100))}`);\n\t\tif (item.snippet) rows.push(theme.fg(\"muted\", ` ${shorten(item.snippet, 140)}`));\n\t}\n\tif (details.results.length > visibleLimit) {\n\t\trows.push(theme.fg(\"dim\", `… ${details.results.length - visibleLimit} more sources`));\n\t}\n\treturn new Text(rows.join(\"\\n\"), 0, 0);\n}\n"]}
|
|
@@ -4,7 +4,12 @@ export interface SearchRoutingState {
|
|
|
4
4
|
successCounts: number[];
|
|
5
5
|
}
|
|
6
6
|
export declare function createSearchRoutingState(providerCount: number): SearchRoutingState;
|
|
7
|
-
export
|
|
7
|
+
export declare function providerEntryLabel(entry: {
|
|
8
|
+
readonly provider: string;
|
|
9
|
+
readonly id?: string;
|
|
10
|
+
readonly entryId?: string;
|
|
11
|
+
}): string;
|
|
12
|
+
export type SearchAttemptListener = (providerLabel: string, attempts: readonly SearchAttempt[], routeLabels: readonly string[]) => void;
|
|
8
13
|
export declare function performSearch(config: WebsearchConfig, request: SearchRequest, signal?: AbortSignal, routingState?: SearchRoutingState, onAttempt?: SearchAttemptListener): Promise<SearchDetails>;
|
|
9
14
|
export declare function formatSearchText(details: SearchDetails): string;
|
|
10
15
|
//# sourceMappingURL=search.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGX,aAAa,EACb,aAAa,EAEb,aAAa,EACb,eAAe,EACf,MAAM,YAAY,CAAC;AAyEpB,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,MAAM,GAAG,kBAAkB,CAElF;
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGX,aAAa,EACb,aAAa,EAEb,aAAa,EACb,eAAe,EACf,MAAM,YAAY,CAAC;AAyEpB,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,MAAM,GAAG,kBAAkB,CAElF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,MAAM,CAKT;AAuJD,MAAM,MAAM,qBAAqB,GAAG,CACnC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,SAAS,aAAa,EAAE,EAClC,WAAW,EAAE,SAAS,MAAM,EAAE,KAC1B,IAAI,CAAC;AAEV,wBAAsB,aAAa,CAClC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,aAAa,EACtB,MAAM,CAAC,EAAE,WAAW,EACpB,YAAY,CAAC,EAAE,kBAAkB,EACjC,SAAS,CAAC,EAAE,qBAAqB,GAC/B,OAAO,CAAC,aAAa,CAAC,CAqExB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CA0B/D"}
|
|
@@ -58,17 +58,17 @@ function searchAbortSignal(outerSignal, timeoutMs) {
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
function noResultsMessage(config, request) {
|
|
61
|
-
return `Search provider ${
|
|
61
|
+
return `Search provider ${providerEntryLabel(config)} returned no results for "${request.query}".`;
|
|
62
62
|
}
|
|
63
63
|
export function createSearchRoutingState(providerCount) {
|
|
64
64
|
return { roundRobinCursor: 0, successCounts: Array.from({ length: providerCount }, () => 0) };
|
|
65
65
|
}
|
|
66
|
-
function
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return entry.provider
|
|
66
|
+
export function providerEntryLabel(entry) {
|
|
67
|
+
const id = entry.entryId ?? entry.id;
|
|
68
|
+
if (!id || id === entry.provider)
|
|
69
|
+
return entry.provider;
|
|
70
|
+
const nativePrefix = `native-${entry.provider}-`;
|
|
71
|
+
return `${entry.provider}/${id.startsWith(nativePrefix) ? "native" : id}`;
|
|
72
72
|
}
|
|
73
73
|
function sortedPriorityIndices(providers) {
|
|
74
74
|
return providers
|
|
@@ -230,13 +230,17 @@ export async function performSearch(config, request, signal, routingState, onAtt
|
|
|
230
230
|
const state = routingState ?? createSearchRoutingState(config.providers.length);
|
|
231
231
|
const order = selectOrder(config.strategy, config.providers, state);
|
|
232
232
|
const attempts = [];
|
|
233
|
+
const routeLabels = order.flatMap((index) => {
|
|
234
|
+
const provider = config.providers[index];
|
|
235
|
+
return provider ? [providerEntryLabel(provider)] : [];
|
|
236
|
+
});
|
|
233
237
|
const collected = new Map();
|
|
234
238
|
let selectedDetails;
|
|
235
239
|
for (const index of order) {
|
|
236
240
|
const provider = config.providers[index];
|
|
237
241
|
if (!provider)
|
|
238
242
|
continue;
|
|
239
|
-
onAttempt?.(
|
|
243
|
+
onAttempt?.(providerEntryLabel(provider), attempts, routeLabels);
|
|
240
244
|
const details = await performProviderSearch(provider, request, signal);
|
|
241
245
|
attempts.push(attemptFromDetails(details));
|
|
242
246
|
if (details.error) {
|
|
@@ -286,7 +290,7 @@ export async function performSearch(config, request, signal, routingState, onAtt
|
|
|
286
290
|
durationMs: Date.now() - startedAt,
|
|
287
291
|
strategy: config.strategy,
|
|
288
292
|
attempts,
|
|
289
|
-
error: `All configured search providers failed: ${attempts.map((attempt) => `${
|
|
293
|
+
error: `All configured search providers failed: ${attempts.map((attempt) => `${providerEntryLabel(attempt)} ${attempt.error ?? "failed"}`).join("; ")}`,
|
|
290
294
|
};
|
|
291
295
|
}
|
|
292
296
|
export function formatSearchText(details) {
|
|
@@ -295,12 +299,12 @@ export function formatSearchText(details) {
|
|
|
295
299
|
if (details.results.length === 0)
|
|
296
300
|
return `No web search results found for "${details.query}".`;
|
|
297
301
|
const route = details.strategy
|
|
298
|
-
? ` via ${details
|
|
302
|
+
? ` via ${providerEntryLabel(details)} (${details.strategy})`
|
|
299
303
|
: ` via ${details.provider}`;
|
|
300
304
|
const lines = [`Web search results for "${details.query}"${route}:`, ""];
|
|
301
305
|
if (details.attempts && details.attempts.length > 0) {
|
|
302
306
|
lines.push(`Routing attempts: ${details.attempts
|
|
303
|
-
.map((attempt) => `${
|
|
307
|
+
.map((attempt) => `${providerEntryLabel(attempt)} ${attempt.error ? `failed: ${attempt.error}` : `${attempt.resultsCount} result${attempt.resultsCount === 1 ? "" : "s"}`}`)
|
|
304
308
|
.join(" -> ")}`, "");
|
|
305
309
|
}
|
|
306
310
|
for (const [index, item] of details.results.entries()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/search.ts"],"names":[],"mappings":"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","sourcesContent":["import { buildSearchRequest, normalizeSearchResponse } from \"./providers.ts\";\nimport type {\n\tJsonObject,\n\tRoutingStrategy,\n\tSearchAttempt,\n\tSearchDetails,\n\tSearchProviderEntry,\n\tSearchRequest,\n\tWebsearchConfig,\n} from \"./types.ts\";\n\nconst MAX_ERROR_DETAIL_LENGTH = 500;\nconst DEFAULT_PROVIDER_TIMEOUT_MS = 60_000;\n\nfunction isJsonObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction truncate(value: string, max: number): string {\n\treturn value.length > max ? `${value.slice(0, max - 1)}…` : value;\n}\n\nfunction extractErrorDetail(payload: unknown, bodyText: string): string {\n\tif (isJsonObject(payload)) {\n\t\tconst obj = payload;\n\t\tconst error = obj.error;\n\t\tif (typeof error === \"string\" && error.length > 0) return truncate(error, MAX_ERROR_DETAIL_LENGTH);\n\t\tif (isJsonObject(error)) {\n\t\t\tconst message = error.message;\n\t\t\tif (typeof message === \"string\" && message.length > 0) return truncate(message, MAX_ERROR_DETAIL_LENGTH);\n\t\t}\n\t\tconst message = obj.message;\n\t\tif (typeof message === \"string\" && message.length > 0) return truncate(message, MAX_ERROR_DETAIL_LENGTH);\n\t}\n\tconst trimmed = bodyText.trim();\n\tif (!trimmed) return \"\";\n\treturn truncate(trimmed, MAX_ERROR_DETAIL_LENGTH);\n}\n\nfunction httpErrorMessage(status: number, payload: unknown, bodyText: string): string {\n\tconst detail = extractErrorDetail(payload, bodyText);\n\treturn detail ? `Search failed with HTTP ${status}: ${detail}` : `Search failed with HTTP ${status}`;\n}\n\nfunction abortReason(signal: AbortSignal): unknown {\n\treturn signal.reason ?? new DOMException(\"The operation was aborted.\", \"AbortError\");\n}\n\nfunction timeoutMsFor(config: SearchProviderEntry): number {\n\treturn Math.max(1, Math.trunc(config.timeoutMs ?? DEFAULT_PROVIDER_TIMEOUT_MS));\n}\n\nfunction providerTimeoutMessage(timeoutMs: number): string {\n\treturn `Search timed out after ${timeoutMs}ms`;\n}\n\nfunction searchAbortSignal(\n\touterSignal: AbortSignal | undefined,\n\ttimeoutMs: number,\n): { signal: AbortSignal; cleanup: () => void } {\n\tif (outerSignal?.aborted) throw abortReason(outerSignal);\n\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => {\n\t\tcontroller.abort(new DOMException(providerTimeoutMessage(timeoutMs), \"TimeoutError\"));\n\t}, timeoutMs);\n\tconst onAbort = () => controller.abort(outerSignal ? abortReason(outerSignal) : undefined);\n\touterSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\treturn {\n\t\tsignal: controller.signal,\n\t\tcleanup: () => {\n\t\t\tclearTimeout(timeout);\n\t\t\touterSignal?.removeEventListener(\"abort\", onAbort);\n\t\t},\n\t};\n}\n\nfunction noResultsMessage(config: SearchProviderEntry, request: SearchRequest): string {\n\treturn `Search provider ${entryLabel(config)} returned no results for \"${request.query}\".`;\n}\n\nexport interface SearchRoutingState {\n\troundRobinCursor: number;\n\tsuccessCounts: number[];\n}\n\nexport function createSearchRoutingState(providerCount: number): SearchRoutingState {\n\treturn { roundRobinCursor: 0, successCounts: Array.from({ length: providerCount }, () => 0) };\n}\n\nfunction entryLabel(entry: Pick<SearchProviderEntry, \"provider\" | \"id\"> | SearchAttempt): string {\n\tif (\"entryId\" in entry && entry.entryId) return `${entry.provider}/${entry.entryId}`;\n\tif (\"id\" in entry && entry.id) return `${entry.provider}/${entry.id}`;\n\treturn entry.provider;\n}\n\nfunction sortedPriorityIndices(providers: SearchProviderEntry[]): number[] {\n\treturn providers\n\t\t.map((provider, index) => ({ index, priority: provider.priority ?? index }))\n\t\t.sort((left, right) => left.priority - right.priority || left.index - right.index)\n\t\t.map((item) => item.index);\n}\n\nfunction weightedIndices(providers: SearchProviderEntry[]): number[] {\n\tconst indices: number[] = [];\n\tfor (const [index, provider] of providers.entries()) {\n\t\tconst weight = Math.max(1, Math.trunc(provider.weight ?? 1));\n\t\tfor (let count = 0; count < weight; count += 1) indices.push(index);\n\t}\n\treturn indices.length > 0 ? indices : providers.map((_provider, index) => index);\n}\n\nfunction rotateUnique(indices: number[], start: number, providerCount: number): number[] {\n\tconst order: number[] = [];\n\tfor (let offset = 0; offset < indices.length; offset += 1) {\n\t\tconst index = indices[(start + offset) % indices.length];\n\t\tif (index !== undefined && !order.includes(index)) order.push(index);\n\t}\n\tfor (let index = 0; index < providerCount; index += 1) {\n\t\tif (!order.includes(index)) order.push(index);\n\t}\n\treturn order;\n}\n\nfunction selectOrder(strategy: RoutingStrategy, providers: SearchProviderEntry[], state: SearchRoutingState): number[] {\n\tif (strategy === \"priority\") return sortedPriorityIndices(providers);\n\tif (strategy === \"round-robin\") {\n\t\tconst indices = weightedIndices(providers);\n\t\tconst order = rotateUnique(indices, state.roundRobinCursor % indices.length, providers.length);\n\t\tstate.roundRobinCursor = (state.roundRobinCursor + 1) % indices.length;\n\t\treturn order;\n\t}\n\n\tlet selected = 0;\n\tlet selectedCount = state.successCounts[0] ?? 0;\n\tfor (let index = 1; index < providers.length; index += 1) {\n\t\tconst count = state.successCounts[index] ?? 0;\n\t\tif (count < selectedCount) {\n\t\t\tselected = index;\n\t\t\tselectedCount = count;\n\t\t}\n\t}\n\treturn [selected, ...providers.map((_provider, index) => index).filter((index) => index !== selected)];\n}\n\nasync function performProviderSearch(\n\tconfig: SearchProviderEntry,\n\trequest: SearchRequest,\n\tsignal?: AbortSignal,\n): Promise<SearchDetails> {\n\tconst startedAt = Date.now();\n\tconst built = buildSearchRequest(config, request);\n\tconst timeoutMs = timeoutMsFor(config);\n\tconst abort = searchAbortSignal(signal, timeoutMs);\n\tlet response: Response;\n\ttry {\n\t\tconst init: RequestInit = {\n\t\t\t...built.init,\n\t\t\tsignal: abort.signal,\n\t\t};\n\t\tif (built.body !== undefined) init.body = JSON.stringify(built.body);\n\t\tresponse = await fetch(built.url, init);\n\t} catch (error) {\n\t\tabort.cleanup();\n\t\tif (signal?.aborted) throw abortReason(signal);\n\t\tconst details: SearchDetails = {\n\t\t\tprovider: config.provider,\n\t\t\tquery: request.query,\n\t\t\tresults: [],\n\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\ttruncated: false,\n\t\t\terror: error instanceof Error ? error.message : \"Search request failed\",\n\t\t};\n\t\tif (config.id !== undefined) details.entryId = config.id;\n\t\treturn details;\n\t}\n\n\tlet bodyText = \"\";\n\ttry {\n\t\tbodyText = await response.text();\n\t} catch (error) {\n\t\tabort.cleanup();\n\t\tif (signal?.aborted) throw abortReason(signal);\n\t\tconst details: SearchDetails = {\n\t\t\tprovider: config.provider,\n\t\t\tquery: request.query,\n\t\t\tresults: [],\n\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\ttruncated: false,\n\t\t\terror: error instanceof Error ? error.message : \"Search response read failed\",\n\t\t};\n\t\tif (config.id !== undefined) details.entryId = config.id;\n\t\treturn details;\n\t} finally {\n\t\tabort.cleanup();\n\t}\n\tlet payload: unknown = {};\n\tif (config.provider === \"duckduckgo-html\") {\n\t\tpayload = { html: bodyText };\n\t} else if (bodyText.length > 0) {\n\t\ttry {\n\t\t\tpayload = JSON.parse(bodyText);\n\t\t} catch {\n\t\t\tpayload = {};\n\t\t}\n\t}\n\tif (!response.ok) {\n\t\tconst details: SearchDetails = {\n\t\t\tprovider: config.provider,\n\t\t\tquery: request.query,\n\t\t\tresults: [],\n\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\ttruncated: false,\n\t\t\terror: httpErrorMessage(response.status, payload, bodyText),\n\t\t};\n\t\tif (config.id !== undefined) details.entryId = config.id;\n\t\treturn details;\n\t}\n\n\tconst results = normalizeSearchResponse(config.provider, payload);\n\tconst max = request.maxResults;\n\tconst limitedResults = results.slice(0, max);\n\tconst details: SearchDetails = {\n\t\tprovider: config.provider,\n\t\tquery: request.query,\n\t\tresults: limitedResults,\n\t\tdurationMs: Date.now() - startedAt,\n\t\ttruncated: results.length > max,\n\t};\n\tif (limitedResults.length === 0) details.error = noResultsMessage(config, request);\n\tif (config.id !== undefined) details.entryId = config.id;\n\treturn details;\n}\n\nfunction attemptFromDetails(details: SearchDetails): SearchAttempt {\n\tconst attempt: SearchAttempt = {\n\t\tprovider: details.provider,\n\t\tdurationMs: details.durationMs,\n\t\tresultsCount: details.results.length,\n\t};\n\tif (details.entryId) attempt.entryId = details.entryId;\n\tif (details.error) attempt.error = details.error;\n\treturn attempt;\n}\n\nexport type SearchAttemptListener = (providerLabel: string, attempts: readonly SearchAttempt[]) => void;\n\nexport async function performSearch(\n\tconfig: WebsearchConfig,\n\trequest: SearchRequest,\n\tsignal?: AbortSignal,\n\troutingState?: SearchRoutingState,\n\tonAttempt?: SearchAttemptListener,\n): Promise<SearchDetails> {\n\tconst startedAt = Date.now();\n\tconst state = routingState ?? createSearchRoutingState(config.providers.length);\n\tconst order = selectOrder(config.strategy, config.providers, state);\n\tconst attempts: SearchAttempt[] = [];\n\tconst collected = new Map<string, SearchDetails[\"results\"][number]>();\n\tlet selectedDetails: SearchDetails | undefined;\n\n\tfor (const index of order) {\n\t\tconst provider = config.providers[index];\n\t\tif (!provider) continue;\n\t\tonAttempt?.(entryLabel(provider), attempts);\n\t\tconst details = await performProviderSearch(provider, request, signal);\n\t\tattempts.push(attemptFromDetails(details));\n\n\t\tif (details.error) {\n\t\t\tif (!config.fallback) return { ...details, strategy: config.strategy, attempts };\n\t\t\tselectedDetails = details;\n\t\t\tcontinue;\n\t\t}\n\n\t\tstate.successCounts[index] = (state.successCounts[index] ?? 0) + 1;\n\n\t\tif (config.strategy !== \"fill-first\") {\n\t\t\treturn { ...details, strategy: config.strategy, attempts };\n\t\t}\n\n\t\tselectedDetails = details;\n\t\tfor (const item of details.results) {\n\t\t\tif (collected.size >= request.maxResults) break;\n\t\t\tcollected.set(item.url, item);\n\t\t}\n\t\tif (collected.size >= request.maxResults) break;\n\t}\n\n\tif (collected.size > 0 && selectedDetails) {\n\t\tconst results = [...collected.values()];\n\t\tconst details: SearchDetails = {\n\t\t\tprovider: selectedDetails.provider,\n\t\t\tquery: request.query,\n\t\t\tresults,\n\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\ttruncated: results.length >= request.maxResults,\n\t\t\tstrategy: config.strategy,\n\t\t\tattempts,\n\t\t};\n\t\tif (selectedDetails.entryId !== undefined) details.entryId = selectedDetails.entryId;\n\t\treturn details;\n\t}\n\n\tconst failed = selectedDetails ?? {\n\t\tprovider: config.providers[0]?.provider ?? \"exa\",\n\t\tquery: request.query,\n\t\tresults: [],\n\t\tdurationMs: Date.now() - startedAt,\n\t\ttruncated: false,\n\t\terror: \"All configured search providers failed.\",\n\t};\n\treturn {\n\t\t...failed,\n\t\tdurationMs: Date.now() - startedAt,\n\t\tstrategy: config.strategy,\n\t\tattempts,\n\t\terror: `All configured search providers failed: ${attempts.map((attempt) => `${entryLabel(attempt)} ${attempt.error ?? \"failed\"}`).join(\"; \")}`,\n\t};\n}\n\nexport function formatSearchText(details: SearchDetails): string {\n\tif (details.error) return details.error;\n\tif (details.results.length === 0) return `No web search results found for \"${details.query}\".`;\n\n\tconst route = details.strategy\n\t\t? ` via ${details.entryId ? `${details.provider}/${details.entryId}` : details.provider} (${details.strategy})`\n\t\t: ` via ${details.provider}`;\n\tconst lines = [`Web search results for \"${details.query}\"${route}:`, \"\"];\n\tif (details.attempts && details.attempts.length > 0) {\n\t\tlines.push(\n\t\t\t`Routing attempts: ${details.attempts\n\t\t\t\t.map(\n\t\t\t\t\t(attempt) =>\n\t\t\t\t\t\t`${entryLabel(attempt)} ${attempt.error ? `failed: ${attempt.error}` : `${attempt.resultsCount} result${attempt.resultsCount === 1 ? \"\" : \"s\"}`}`,\n\t\t\t\t)\n\t\t\t\t.join(\" -> \")}`,\n\t\t\t\"\",\n\t\t);\n\t}\n\tfor (const [index, item] of details.results.entries()) {\n\t\tlines.push(`${index + 1}. ${item.title}`);\n\t\tlines.push(` ${item.url}`);\n\t\tif (item.snippet) lines.push(` ${item.snippet}`);\n\t}\n\tlines.push(\"\", \"REMINDER: Include relevant sources from the URLs above in the final answer.\");\n\treturn lines.join(\"\\n\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/search.ts"],"names":[],"mappings":"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","sourcesContent":["import { buildSearchRequest, normalizeSearchResponse } from \"./providers.ts\";\nimport type {\n\tJsonObject,\n\tRoutingStrategy,\n\tSearchAttempt,\n\tSearchDetails,\n\tSearchProviderEntry,\n\tSearchRequest,\n\tWebsearchConfig,\n} from \"./types.ts\";\n\nconst MAX_ERROR_DETAIL_LENGTH = 500;\nconst DEFAULT_PROVIDER_TIMEOUT_MS = 60_000;\n\nfunction isJsonObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction truncate(value: string, max: number): string {\n\treturn value.length > max ? `${value.slice(0, max - 1)}…` : value;\n}\n\nfunction extractErrorDetail(payload: unknown, bodyText: string): string {\n\tif (isJsonObject(payload)) {\n\t\tconst obj = payload;\n\t\tconst error = obj.error;\n\t\tif (typeof error === \"string\" && error.length > 0) return truncate(error, MAX_ERROR_DETAIL_LENGTH);\n\t\tif (isJsonObject(error)) {\n\t\t\tconst message = error.message;\n\t\t\tif (typeof message === \"string\" && message.length > 0) return truncate(message, MAX_ERROR_DETAIL_LENGTH);\n\t\t}\n\t\tconst message = obj.message;\n\t\tif (typeof message === \"string\" && message.length > 0) return truncate(message, MAX_ERROR_DETAIL_LENGTH);\n\t}\n\tconst trimmed = bodyText.trim();\n\tif (!trimmed) return \"\";\n\treturn truncate(trimmed, MAX_ERROR_DETAIL_LENGTH);\n}\n\nfunction httpErrorMessage(status: number, payload: unknown, bodyText: string): string {\n\tconst detail = extractErrorDetail(payload, bodyText);\n\treturn detail ? `Search failed with HTTP ${status}: ${detail}` : `Search failed with HTTP ${status}`;\n}\n\nfunction abortReason(signal: AbortSignal): unknown {\n\treturn signal.reason ?? new DOMException(\"The operation was aborted.\", \"AbortError\");\n}\n\nfunction timeoutMsFor(config: SearchProviderEntry): number {\n\treturn Math.max(1, Math.trunc(config.timeoutMs ?? DEFAULT_PROVIDER_TIMEOUT_MS));\n}\n\nfunction providerTimeoutMessage(timeoutMs: number): string {\n\treturn `Search timed out after ${timeoutMs}ms`;\n}\n\nfunction searchAbortSignal(\n\touterSignal: AbortSignal | undefined,\n\ttimeoutMs: number,\n): { signal: AbortSignal; cleanup: () => void } {\n\tif (outerSignal?.aborted) throw abortReason(outerSignal);\n\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => {\n\t\tcontroller.abort(new DOMException(providerTimeoutMessage(timeoutMs), \"TimeoutError\"));\n\t}, timeoutMs);\n\tconst onAbort = () => controller.abort(outerSignal ? abortReason(outerSignal) : undefined);\n\touterSignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\treturn {\n\t\tsignal: controller.signal,\n\t\tcleanup: () => {\n\t\t\tclearTimeout(timeout);\n\t\t\touterSignal?.removeEventListener(\"abort\", onAbort);\n\t\t},\n\t};\n}\n\nfunction noResultsMessage(config: SearchProviderEntry, request: SearchRequest): string {\n\treturn `Search provider ${providerEntryLabel(config)} returned no results for \"${request.query}\".`;\n}\n\nexport interface SearchRoutingState {\n\troundRobinCursor: number;\n\tsuccessCounts: number[];\n}\n\nexport function createSearchRoutingState(providerCount: number): SearchRoutingState {\n\treturn { roundRobinCursor: 0, successCounts: Array.from({ length: providerCount }, () => 0) };\n}\n\nexport function providerEntryLabel(entry: {\n\treadonly provider: string;\n\treadonly id?: string;\n\treadonly entryId?: string;\n}): string {\n\tconst id = entry.entryId ?? entry.id;\n\tif (!id || id === entry.provider) return entry.provider;\n\tconst nativePrefix = `native-${entry.provider}-`;\n\treturn `${entry.provider}/${id.startsWith(nativePrefix) ? \"native\" : id}`;\n}\n\nfunction sortedPriorityIndices(providers: SearchProviderEntry[]): number[] {\n\treturn providers\n\t\t.map((provider, index) => ({ index, priority: provider.priority ?? index }))\n\t\t.sort((left, right) => left.priority - right.priority || left.index - right.index)\n\t\t.map((item) => item.index);\n}\n\nfunction weightedIndices(providers: SearchProviderEntry[]): number[] {\n\tconst indices: number[] = [];\n\tfor (const [index, provider] of providers.entries()) {\n\t\tconst weight = Math.max(1, Math.trunc(provider.weight ?? 1));\n\t\tfor (let count = 0; count < weight; count += 1) indices.push(index);\n\t}\n\treturn indices.length > 0 ? indices : providers.map((_provider, index) => index);\n}\n\nfunction rotateUnique(indices: number[], start: number, providerCount: number): number[] {\n\tconst order: number[] = [];\n\tfor (let offset = 0; offset < indices.length; offset += 1) {\n\t\tconst index = indices[(start + offset) % indices.length];\n\t\tif (index !== undefined && !order.includes(index)) order.push(index);\n\t}\n\tfor (let index = 0; index < providerCount; index += 1) {\n\t\tif (!order.includes(index)) order.push(index);\n\t}\n\treturn order;\n}\n\nfunction selectOrder(strategy: RoutingStrategy, providers: SearchProviderEntry[], state: SearchRoutingState): number[] {\n\tif (strategy === \"priority\") return sortedPriorityIndices(providers);\n\tif (strategy === \"round-robin\") {\n\t\tconst indices = weightedIndices(providers);\n\t\tconst order = rotateUnique(indices, state.roundRobinCursor % indices.length, providers.length);\n\t\tstate.roundRobinCursor = (state.roundRobinCursor + 1) % indices.length;\n\t\treturn order;\n\t}\n\n\tlet selected = 0;\n\tlet selectedCount = state.successCounts[0] ?? 0;\n\tfor (let index = 1; index < providers.length; index += 1) {\n\t\tconst count = state.successCounts[index] ?? 0;\n\t\tif (count < selectedCount) {\n\t\t\tselected = index;\n\t\t\tselectedCount = count;\n\t\t}\n\t}\n\treturn [selected, ...providers.map((_provider, index) => index).filter((index) => index !== selected)];\n}\n\nasync function performProviderSearch(\n\tconfig: SearchProviderEntry,\n\trequest: SearchRequest,\n\tsignal?: AbortSignal,\n): Promise<SearchDetails> {\n\tconst startedAt = Date.now();\n\tconst built = buildSearchRequest(config, request);\n\tconst timeoutMs = timeoutMsFor(config);\n\tconst abort = searchAbortSignal(signal, timeoutMs);\n\tlet response: Response;\n\ttry {\n\t\tconst init: RequestInit = {\n\t\t\t...built.init,\n\t\t\tsignal: abort.signal,\n\t\t};\n\t\tif (built.body !== undefined) init.body = JSON.stringify(built.body);\n\t\tresponse = await fetch(built.url, init);\n\t} catch (error) {\n\t\tabort.cleanup();\n\t\tif (signal?.aborted) throw abortReason(signal);\n\t\tconst details: SearchDetails = {\n\t\t\tprovider: config.provider,\n\t\t\tquery: request.query,\n\t\t\tresults: [],\n\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\ttruncated: false,\n\t\t\terror: error instanceof Error ? error.message : \"Search request failed\",\n\t\t};\n\t\tif (config.id !== undefined) details.entryId = config.id;\n\t\treturn details;\n\t}\n\n\tlet bodyText = \"\";\n\ttry {\n\t\tbodyText = await response.text();\n\t} catch (error) {\n\t\tabort.cleanup();\n\t\tif (signal?.aborted) throw abortReason(signal);\n\t\tconst details: SearchDetails = {\n\t\t\tprovider: config.provider,\n\t\t\tquery: request.query,\n\t\t\tresults: [],\n\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\ttruncated: false,\n\t\t\terror: error instanceof Error ? error.message : \"Search response read failed\",\n\t\t};\n\t\tif (config.id !== undefined) details.entryId = config.id;\n\t\treturn details;\n\t} finally {\n\t\tabort.cleanup();\n\t}\n\tlet payload: unknown = {};\n\tif (config.provider === \"duckduckgo-html\") {\n\t\tpayload = { html: bodyText };\n\t} else if (bodyText.length > 0) {\n\t\ttry {\n\t\t\tpayload = JSON.parse(bodyText);\n\t\t} catch {\n\t\t\tpayload = {};\n\t\t}\n\t}\n\tif (!response.ok) {\n\t\tconst details: SearchDetails = {\n\t\t\tprovider: config.provider,\n\t\t\tquery: request.query,\n\t\t\tresults: [],\n\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\ttruncated: false,\n\t\t\terror: httpErrorMessage(response.status, payload, bodyText),\n\t\t};\n\t\tif (config.id !== undefined) details.entryId = config.id;\n\t\treturn details;\n\t}\n\n\tconst results = normalizeSearchResponse(config.provider, payload);\n\tconst max = request.maxResults;\n\tconst limitedResults = results.slice(0, max);\n\tconst details: SearchDetails = {\n\t\tprovider: config.provider,\n\t\tquery: request.query,\n\t\tresults: limitedResults,\n\t\tdurationMs: Date.now() - startedAt,\n\t\ttruncated: results.length > max,\n\t};\n\tif (limitedResults.length === 0) details.error = noResultsMessage(config, request);\n\tif (config.id !== undefined) details.entryId = config.id;\n\treturn details;\n}\n\nfunction attemptFromDetails(details: SearchDetails): SearchAttempt {\n\tconst attempt: SearchAttempt = {\n\t\tprovider: details.provider,\n\t\tdurationMs: details.durationMs,\n\t\tresultsCount: details.results.length,\n\t};\n\tif (details.entryId) attempt.entryId = details.entryId;\n\tif (details.error) attempt.error = details.error;\n\treturn attempt;\n}\n\nexport type SearchAttemptListener = (\n\tproviderLabel: string,\n\tattempts: readonly SearchAttempt[],\n\trouteLabels: readonly string[],\n) => void;\n\nexport async function performSearch(\n\tconfig: WebsearchConfig,\n\trequest: SearchRequest,\n\tsignal?: AbortSignal,\n\troutingState?: SearchRoutingState,\n\tonAttempt?: SearchAttemptListener,\n): Promise<SearchDetails> {\n\tconst startedAt = Date.now();\n\tconst state = routingState ?? createSearchRoutingState(config.providers.length);\n\tconst order = selectOrder(config.strategy, config.providers, state);\n\tconst attempts: SearchAttempt[] = [];\n\tconst routeLabels = order.flatMap((index) => {\n\t\tconst provider = config.providers[index];\n\t\treturn provider ? [providerEntryLabel(provider)] : [];\n\t});\n\tconst collected = new Map<string, SearchDetails[\"results\"][number]>();\n\tlet selectedDetails: SearchDetails | undefined;\n\n\tfor (const index of order) {\n\t\tconst provider = config.providers[index];\n\t\tif (!provider) continue;\n\t\tonAttempt?.(providerEntryLabel(provider), attempts, routeLabels);\n\t\tconst details = await performProviderSearch(provider, request, signal);\n\t\tattempts.push(attemptFromDetails(details));\n\n\t\tif (details.error) {\n\t\t\tif (!config.fallback) return { ...details, strategy: config.strategy, attempts };\n\t\t\tselectedDetails = details;\n\t\t\tcontinue;\n\t\t}\n\n\t\tstate.successCounts[index] = (state.successCounts[index] ?? 0) + 1;\n\n\t\tif (config.strategy !== \"fill-first\") {\n\t\t\treturn { ...details, strategy: config.strategy, attempts };\n\t\t}\n\n\t\tselectedDetails = details;\n\t\tfor (const item of details.results) {\n\t\t\tif (collected.size >= request.maxResults) break;\n\t\t\tcollected.set(item.url, item);\n\t\t}\n\t\tif (collected.size >= request.maxResults) break;\n\t}\n\n\tif (collected.size > 0 && selectedDetails) {\n\t\tconst results = [...collected.values()];\n\t\tconst details: SearchDetails = {\n\t\t\tprovider: selectedDetails.provider,\n\t\t\tquery: request.query,\n\t\t\tresults,\n\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\ttruncated: results.length >= request.maxResults,\n\t\t\tstrategy: config.strategy,\n\t\t\tattempts,\n\t\t};\n\t\tif (selectedDetails.entryId !== undefined) details.entryId = selectedDetails.entryId;\n\t\treturn details;\n\t}\n\n\tconst failed = selectedDetails ?? {\n\t\tprovider: config.providers[0]?.provider ?? \"exa\",\n\t\tquery: request.query,\n\t\tresults: [],\n\t\tdurationMs: Date.now() - startedAt,\n\t\ttruncated: false,\n\t\terror: \"All configured search providers failed.\",\n\t};\n\treturn {\n\t\t...failed,\n\t\tdurationMs: Date.now() - startedAt,\n\t\tstrategy: config.strategy,\n\t\tattempts,\n\t\terror: `All configured search providers failed: ${attempts.map((attempt) => `${providerEntryLabel(attempt)} ${attempt.error ?? \"failed\"}`).join(\"; \")}`,\n\t};\n}\n\nexport function formatSearchText(details: SearchDetails): string {\n\tif (details.error) return details.error;\n\tif (details.results.length === 0) return `No web search results found for \"${details.query}\".`;\n\n\tconst route = details.strategy\n\t\t? ` via ${providerEntryLabel(details)} (${details.strategy})`\n\t\t: ` via ${details.provider}`;\n\tconst lines = [`Web search results for \"${details.query}\"${route}:`, \"\"];\n\tif (details.attempts && details.attempts.length > 0) {\n\t\tlines.push(\n\t\t\t`Routing attempts: ${details.attempts\n\t\t\t\t.map(\n\t\t\t\t\t(attempt) =>\n\t\t\t\t\t\t`${providerEntryLabel(attempt)} ${attempt.error ? `failed: ${attempt.error}` : `${attempt.resultsCount} result${attempt.resultsCount === 1 ? \"\" : \"s\"}`}`,\n\t\t\t\t)\n\t\t\t\t.join(\" -> \")}`,\n\t\t\t\"\",\n\t\t);\n\t}\n\tfor (const [index, item] of details.results.entries()) {\n\t\tlines.push(`${index + 1}. ${item.title}`);\n\t\tlines.push(` ${item.url}`);\n\t\tif (item.snippet) lines.push(` ${item.snippet}`);\n\t}\n\tlines.push(\"\", \"REMINDER: Include relevant sources from the URLs above in the final answer.\");\n\treturn lines.join(\"\\n\");\n}\n"]}
|