@astralyn/pi 1.0.5 → 1.1.0
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 +37 -0
- package/dist/bundle/chunks/{anthropic-messages-YIOJIMVL.js → anthropic-messages-3K3DWVY6.js} +1 -1
- package/dist/bundle/chunks/anthropic.js +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-LDW4FGAQ.js → azure-openai-responses-CH74HGP4.js} +1 -1
- package/dist/bundle/chunks/bedrock-converse-stream.js +2 -2
- package/dist/bundle/chunks/{chunk-UCXU7KLO.js → chunk-3MMB5I7J.js} +1 -1
- package/dist/bundle/chunks/{chunk-GIG5IHES.js → chunk-5KJH3GGH.js} +1 -1
- package/dist/bundle/chunks/chunk-6VYRLG5F.js +2 -0
- package/dist/bundle/chunks/{chunk-HDHRZ7GT.js → chunk-C2ARIVS3.js} +1 -1
- package/dist/bundle/chunks/{chunk-IE3Z7ESB.js → chunk-D3XW5X3Z.js} +371 -246
- package/dist/bundle/chunks/{chunk-IFELM7MW.js → chunk-EJEOEBSJ.js} +1 -1
- package/dist/bundle/chunks/chunk-H35KWBT5.js +11 -0
- package/dist/bundle/chunks/chunk-KAC2YPTW.js +2 -0
- package/dist/bundle/chunks/chunk-MAC4N3BW.js +2 -0
- package/dist/bundle/chunks/chunk-QLU3LESZ.js +2 -0
- package/dist/bundle/chunks/{chunk-A6ALEEY5.js → chunk-TEAAYBTS.js} +1 -1
- package/dist/bundle/chunks/cloudflare-workers-ai-system-one-XO45ZT3V.js +2 -0
- package/dist/bundle/chunks/codemode-worker.js +2 -2
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/{google-generative-ai-S5A5IBU4.js → google-generative-ai-VVO64ZRQ.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-UBRQFDB4.js → google-vertex-LKS5NUHA.js} +1 -1
- package/dist/bundle/chunks/image-resize-worker.js +1 -1
- package/dist/bundle/chunks/{llama-cpp-classify-R7DQLTQN.js → llama-cpp-classify-H3IZDR5O.js} +2 -2
- package/dist/bundle/chunks/{mistral-conversations-A2N5FSOV.js → mistral-conversations-NJUOG4ET.js} +2 -2
- package/dist/bundle/chunks/openai-chatgpt.js +1 -1
- package/dist/bundle/chunks/{openai-codex-responses-Q6JHCWLE.js → openai-codex-responses-TZWBTTYM.js} +2 -2
- package/dist/bundle/chunks/openai-codex.js +1 -1
- package/dist/bundle/chunks/{openai-completions-H4VMO7AU.js → openai-completions-7HTTU6FH.js} +1 -1
- package/dist/bundle/chunks/openai-decisions-776H4VDZ.js +5 -0
- package/dist/bundle/chunks/{openai-responses-G4PGNM2H.js → openai-responses-7A6BAQ5X.js} +1 -1
- package/dist/bundle/chunks/{openrouter-images-YP3YVB54.js → openrouter-images-TDLJV5N4.js} +1 -1
- package/dist/bundle/chunks/{pi-messages-HZZ7GEEW.js → pi-messages-ZXNERWJG.js} +1 -1
- package/dist/bundle/chunks/typesafe-system-one-2DQLG4R2.js +2 -0
- package/dist/bundle/chunks/{virtual-modules-46MSJGKO.js → virtual-modules-2NHGQRS6.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +13 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session.d.ts +12 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +146 -174
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +40 -45
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/context-snapshot.d.ts +4 -1
- package/dist/core/context-snapshot.d.ts.map +1 -1
- package/dist/core/context-snapshot.js +45 -0
- package/dist/core/context-snapshot.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +2 -0
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/types.d.ts +11 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +2 -1
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/nested-tool-calls.d.ts +1 -0
- package/dist/core/nested-tool-calls.d.ts.map +1 -1
- package/dist/core/nested-tool-calls.js +1 -0
- package/dist/core/nested-tool-calls.js.map +1 -1
- package/dist/core/sdk.d.ts +4 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +17 -5
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager.d.ts +13 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +37 -13
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tasks/session.d.ts +9 -0
- package/dist/core/tasks/session.d.ts.map +1 -1
- package/dist/core/tasks/session.js +21 -0
- package/dist/core/tasks/session.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts.map +1 -1
- package/dist/core/tools/renderers/bash.js +8 -3
- package/dist/core/tools/renderers/bash.js.map +1 -1
- package/dist/core/tools/renderers/edit.js +1 -1
- package/dist/core/tools/renderers/edit.js.map +1 -1
- package/dist/extensions/codemode/execute.d.ts.map +1 -1
- package/dist/extensions/codemode/execute.js +63 -7
- package/dist/extensions/codemode/execute.js.map +1 -1
- package/dist/extensions/codemode/tool.js +2 -2
- package/dist/extensions/codemode/tool.js.map +1 -1
- package/dist/extensions/index.js +2 -2
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +34 -11
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/extensions/mcp/cli.js +17 -23
- package/dist/extensions/mcp/cli.js.map +1 -1
- package/dist/extensions/mcp/index.d.ts.map +1 -1
- package/dist/extensions/mcp/index.js +165 -64
- package/dist/extensions/mcp/index.js.map +1 -1
- package/dist/extensions/mcp/oauth.d.ts +5 -3
- package/dist/extensions/mcp/oauth.d.ts.map +1 -1
- package/dist/extensions/mcp/oauth.js +36 -10
- package/dist/extensions/mcp/oauth.js.map +1 -1
- package/dist/extensions/mcp/ui.d.ts +3 -3
- package/dist/extensions/mcp/ui.d.ts.map +1 -1
- package/dist/extensions/mcp/ui.js +10 -2
- package/dist/extensions/mcp/ui.js.map +1 -1
- package/dist/extensions/search/code-search.d.ts +29 -0
- package/dist/extensions/search/code-search.d.ts.map +1 -0
- package/dist/extensions/search/code-search.js +120 -0
- package/dist/extensions/search/code-search.js.map +1 -0
- package/dist/extensions/search/command.d.ts +5 -0
- package/dist/extensions/search/command.d.ts.map +1 -0
- package/dist/extensions/search/command.js +69 -0
- package/dist/extensions/search/command.js.map +1 -0
- package/dist/extensions/search/credential.d.ts +25 -0
- package/dist/extensions/search/credential.d.ts.map +1 -0
- package/dist/extensions/search/credential.js +117 -0
- package/dist/extensions/search/credential.js.map +1 -0
- package/dist/extensions/search/devin.d.ts +34 -0
- package/dist/extensions/search/devin.d.ts.map +1 -0
- package/dist/extensions/search/devin.js +210 -0
- package/dist/extensions/search/devin.js.map +1 -0
- package/dist/extensions/search/index.d.ts +5 -0
- package/dist/extensions/search/index.d.ts.map +1 -0
- package/dist/extensions/search/index.js +110 -0
- package/dist/extensions/search/index.js.map +1 -0
- package/dist/extensions/search/panel.d.ts +53 -0
- package/dist/extensions/search/panel.d.ts.map +1 -0
- package/dist/extensions/search/panel.js +157 -0
- package/dist/extensions/search/panel.js.map +1 -0
- package/dist/extensions/search/prompt.d.ts +14 -0
- package/dist/extensions/search/prompt.d.ts.map +1 -0
- package/dist/extensions/search/prompt.js +221 -0
- package/dist/extensions/search/prompt.js.map +1 -0
- package/dist/extensions/search/render.d.ts +28 -0
- package/dist/extensions/search/render.d.ts.map +1 -0
- package/dist/extensions/search/render.js +86 -0
- package/dist/extensions/search/render.js.map +1 -0
- package/dist/extensions/search/workspace.d.ts +38 -0
- package/dist/extensions/search/workspace.d.ts.map +1 -0
- package/dist/extensions/search/workspace.js +245 -0
- package/dist/extensions/search/workspace.js.map +1 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +5 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +14 -14
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +2 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +5 -2
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +2 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +5 -2
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts +3 -1
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-entry.js +7 -2
- package/dist/modes/interactive/components/custom-entry.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +1 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +1 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +5 -2
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +52 -59
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/program-status-reporter.d.ts +34 -0
- package/dist/modes/interactive/program-status-reporter.d.ts.map +1 -0
- package/dist/modes/interactive/program-status-reporter.js +107 -0
- package/dist/modes/interactive/program-status-reporter.js.map +1 -0
- package/dist/modes/interactive/tasks/host-hooks.d.ts +14 -0
- package/dist/modes/interactive/tasks/host-hooks.d.ts.map +1 -0
- package/dist/modes/interactive/tasks/host-hooks.js +31 -0
- package/dist/modes/interactive/tasks/host-hooks.js.map +1 -0
- package/dist/modes/interactive/tool-view/tool-execution.d.ts +5 -0
- package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/tool-view/tool-execution.js +7 -0
- package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +24 -0
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/ansi.d.ts +8 -0
- package/dist/utils/ansi.d.ts.map +1 -1
- package/dist/utils/ansi.js +30 -11
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +12 -11
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts +12 -0
- package/dist/utils/image-resize-core.d.ts.map +1 -1
- package/dist/utils/image-resize-core.js +5 -0
- package/dist/utils/image-resize-core.js.map +1 -1
- package/dist/utils/image-resize-worker.js +3 -2
- package/dist/utils/image-resize-worker.js.map +1 -1
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +9 -10
- package/dist/utils/image-resize.js.map +1 -1
- package/docs/bundled/README.md +1 -1
- package/docs/bundled/extensions/provider.md +1 -1
- package/docs/bundled/extensions/question.md +1 -1
- package/docs/bundled/extensions/search.md +50 -0
- package/docs/bundled/extensions/statusline.md +15 -41
- package/docs/codemode.md +23 -3
- package/docs/docs.json +0 -4
- package/docs/environment-variables.md +1 -0
- package/docs/extensions.md +5 -1
- package/docs/json.md +2 -2
- package/docs/llama-cpp.md +8 -1
- package/docs/models.md +4 -1
- package/docs/providers.md +17 -0
- package/docs/rpc.md +6 -3
- package/docs/session-format.md +1 -0
- package/docs/settings.md +3 -3
- package/docs/terminal-setup.md +14 -0
- package/docs/usage.md +5 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +54 -54
- package/package.json +13 -11
- package/dist/bundle/chunks/chunk-57XI7YJH.js +0 -2
- package/dist/bundle/chunks/chunk-JI4WGISU.js +0 -2
- package/dist/bundle/chunks/chunk-TCQ4HHQD.js +0 -2
- package/dist/bundle/chunks/chunk-TXJO4AJ7.js +0 -11
- package/dist/bundle/chunks/cloudflare-workers-ai-system-one-OWU5SM6J.js +0 -2
- package/dist/bundle/chunks/typesafe-system-one-KYKKNU3E.js +0 -2
- package/dist/extensions/web-search/auth.d.ts +0 -12
- package/dist/extensions/web-search/auth.d.ts.map +0 -1
- package/dist/extensions/web-search/auth.js +0 -90
- package/dist/extensions/web-search/auth.js.map +0 -1
- package/dist/extensions/web-search/constants.d.ts +0 -13
- package/dist/extensions/web-search/constants.d.ts.map +0 -1
- package/dist/extensions/web-search/constants.js +0 -26
- package/dist/extensions/web-search/constants.js.map +0 -1
- package/dist/extensions/web-search/execute.d.ts +0 -9
- package/dist/extensions/web-search/execute.d.ts.map +0 -1
- package/dist/extensions/web-search/execute.js +0 -96
- package/dist/extensions/web-search/execute.js.map +0 -1
- package/dist/extensions/web-search/format.d.ts +0 -21
- package/dist/extensions/web-search/format.d.ts.map +0 -1
- package/dist/extensions/web-search/format.js +0 -117
- package/dist/extensions/web-search/format.js.map +0 -1
- package/dist/extensions/web-search/index.d.ts +0 -6
- package/dist/extensions/web-search/index.d.ts.map +0 -1
- package/dist/extensions/web-search/index.js +0 -50
- package/dist/extensions/web-search/index.js.map +0 -1
- package/dist/extensions/web-search/providers/deepseek.d.ts +0 -13
- package/dist/extensions/web-search/providers/deepseek.d.ts.map +0 -1
- package/dist/extensions/web-search/providers/deepseek.js +0 -110
- package/dist/extensions/web-search/providers/deepseek.js.map +0 -1
- package/dist/extensions/web-search/providers/http.d.ts +0 -4
- package/dist/extensions/web-search/providers/http.d.ts.map +0 -1
- package/dist/extensions/web-search/providers/http.js +0 -42
- package/dist/extensions/web-search/providers/http.js.map +0 -1
- package/dist/extensions/web-search/providers/minimax.d.ts +0 -12
- package/dist/extensions/web-search/providers/minimax.d.ts.map +0 -1
- package/dist/extensions/web-search/providers/minimax.js +0 -61
- package/dist/extensions/web-search/providers/minimax.js.map +0 -1
- package/dist/extensions/web-search/render.d.ts +0 -15
- package/dist/extensions/web-search/render.d.ts.map +0 -1
- package/dist/extensions/web-search/render.js +0 -142
- package/dist/extensions/web-search/render.js.map +0 -1
- package/dist/extensions/web-search/results.d.ts +0 -35
- package/dist/extensions/web-search/results.d.ts.map +0 -1
- package/dist/extensions/web-search/results.js +0 -167
- package/dist/extensions/web-search/results.js.map +0 -1
- package/dist/extensions/web-search/schema.d.ts +0 -10
- package/dist/extensions/web-search/schema.d.ts.map +0 -1
- package/dist/extensions/web-search/schema.js +0 -36
- package/dist/extensions/web-search/schema.js.map +0 -1
- package/dist/extensions/web-search/types.d.ts +0 -51
- package/dist/extensions/web-search/types.d.ts.map +0 -1
- package/dist/extensions/web-search/types.js +0 -5
- package/dist/extensions/web-search/types.js.map +0 -1
- package/docs/bundled/extensions/web-search.md +0 -46
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Result normalization, bounding, deduplication, and ranking for web_search providers.
|
|
3
|
-
*/
|
|
4
|
-
export const MAX_OUTPUT_HITS = 12;
|
|
5
|
-
export const MAX_QUERY_LENGTH = 500;
|
|
6
|
-
export const MAX_TITLE_LENGTH = 200;
|
|
7
|
-
export const MAX_URL_LENGTH = 2048;
|
|
8
|
-
export const MAX_SNIPPET_LENGTH = 200;
|
|
9
|
-
export const MAX_DATE_LENGTH = 100;
|
|
10
|
-
export const MAX_RELATED_SEARCHES = 8;
|
|
11
|
-
export const MAX_RELATED_SEARCH_LENGTH = 200;
|
|
12
|
-
export const MAX_SYNTHESIS_LENGTH = 6000;
|
|
13
|
-
export const MAX_ERROR_MESSAGE_LENGTH = 500;
|
|
14
|
-
/** Provider arrays are transport-bounded too, but avoid scanning an entire hostile payload. */
|
|
15
|
-
export const MAX_PROVIDER_HIT_SCAN = 200;
|
|
16
|
-
export const MAX_PROVIDER_RELATED_SCAN = 64;
|
|
17
|
-
/** Historical session details predate the current bounds and may contain oversized arrays. */
|
|
18
|
-
export const MAX_HISTORICAL_HIT_SCAN = MAX_OUTPUT_HITS * 20;
|
|
19
|
-
export const MAX_HISTORICAL_SOURCE_SCAN = 32;
|
|
20
|
-
export const MAX_HISTORICAL_RELATED_SCAN = MAX_RELATED_SEARCHES * 8;
|
|
21
|
-
const RRF_K = 60;
|
|
22
|
-
const TRACKING_PARAMS = new Set([
|
|
23
|
-
"utm_source",
|
|
24
|
-
"utm_medium",
|
|
25
|
-
"utm_campaign",
|
|
26
|
-
"utm_term",
|
|
27
|
-
"utm_content",
|
|
28
|
-
"ref",
|
|
29
|
-
"fbclid",
|
|
30
|
-
"gclid",
|
|
31
|
-
"trk",
|
|
32
|
-
"gi",
|
|
33
|
-
]);
|
|
34
|
-
function truncateText(text, maxLength) {
|
|
35
|
-
if (text.length <= maxLength)
|
|
36
|
-
return text;
|
|
37
|
-
if (maxLength <= 3)
|
|
38
|
-
return text.slice(0, maxLength);
|
|
39
|
-
return `${text.slice(0, maxLength - 3).trimEnd()}...`;
|
|
40
|
-
}
|
|
41
|
-
/** Normalize and bound a provider-controlled single-line text field. */
|
|
42
|
-
export function boundSingleLineText(value, maxLength) {
|
|
43
|
-
if (typeof value !== "string")
|
|
44
|
-
return undefined;
|
|
45
|
-
const normalized = value.replace(/\s+/g, " ").trim();
|
|
46
|
-
return normalized ? truncateText(normalized, maxLength) : undefined;
|
|
47
|
-
}
|
|
48
|
-
/** Trim and bound provider-controlled text that intentionally preserves lines. */
|
|
49
|
-
export function boundMultilineText(value, maxLength) {
|
|
50
|
-
if (typeof value !== "string")
|
|
51
|
-
return undefined;
|
|
52
|
-
const normalized = value.trim();
|
|
53
|
-
return normalized ? truncateText(normalized, maxLength) : undefined;
|
|
54
|
-
}
|
|
55
|
-
/** Normalize a usable HTTP(S) source URL without changing non-tracking query values. */
|
|
56
|
-
export function normalizeUrl(rawUrl) {
|
|
57
|
-
if (typeof rawUrl !== "string")
|
|
58
|
-
return undefined;
|
|
59
|
-
const trimmed = rawUrl.trim();
|
|
60
|
-
if (!trimmed || trimmed.length > MAX_URL_LENGTH)
|
|
61
|
-
return undefined;
|
|
62
|
-
try {
|
|
63
|
-
const url = new URL(trimmed);
|
|
64
|
-
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
65
|
-
return undefined;
|
|
66
|
-
url.hash = "";
|
|
67
|
-
for (const parameter of TRACKING_PARAMS) {
|
|
68
|
-
if (url.searchParams.has(parameter))
|
|
69
|
-
url.searchParams.delete(parameter);
|
|
70
|
-
}
|
|
71
|
-
if (url.pathname.length > 1 && url.pathname.endsWith("/")) {
|
|
72
|
-
url.pathname = url.pathname.replace(/\/+$/, "");
|
|
73
|
-
}
|
|
74
|
-
const normalized = url.toString();
|
|
75
|
-
return normalized.length <= MAX_URL_LENGTH ? normalized : undefined;
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function normalizeHit(hit) {
|
|
82
|
-
const url = normalizeUrl(hit.url);
|
|
83
|
-
if (!url)
|
|
84
|
-
return undefined;
|
|
85
|
-
return {
|
|
86
|
-
title: boundSingleLineText(hit.title, MAX_TITLE_LENGTH) ?? url,
|
|
87
|
-
url,
|
|
88
|
-
snippet: boundSingleLineText(hit.snippet, MAX_SNIPPET_LENGTH),
|
|
89
|
-
date: boundSingleLineText(hit.date, MAX_DATE_LENGTH),
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
function isUrlFallbackTitle(title, url) {
|
|
93
|
-
const normalizedTitle = normalizeUrl(title);
|
|
94
|
-
return normalizedTitle !== undefined && normalizedTitle === normalizeUrl(url);
|
|
95
|
-
}
|
|
96
|
-
function reciprocalRankScore(candidate) {
|
|
97
|
-
let score = 0;
|
|
98
|
-
for (const rank of candidate.ranks.values())
|
|
99
|
-
score += 1 / (RRF_K + rank);
|
|
100
|
-
return score;
|
|
101
|
-
}
|
|
102
|
-
function bestRank(candidate) {
|
|
103
|
-
return Math.min(...candidate.ranks.values());
|
|
104
|
-
}
|
|
105
|
-
/** Bound provider results, deduplicate URLs, and rank them with reciprocal-rank fusion. */
|
|
106
|
-
export function fuseSearchHits(results) {
|
|
107
|
-
const candidates = new Map();
|
|
108
|
-
const relatedSearches = new Set();
|
|
109
|
-
let deepseekSynthesis;
|
|
110
|
-
for (const result of results) {
|
|
111
|
-
const providerRelated = Array.isArray(result.relatedSearches) ? result.relatedSearches : [];
|
|
112
|
-
const relatedScanLimit = Math.min(providerRelated.length, MAX_PROVIDER_RELATED_SCAN);
|
|
113
|
-
for (let index = 0; index < relatedScanLimit && relatedSearches.size < MAX_RELATED_SEARCHES; index++) {
|
|
114
|
-
const normalized = boundSingleLineText(providerRelated[index], MAX_RELATED_SEARCH_LENGTH);
|
|
115
|
-
if (normalized)
|
|
116
|
-
relatedSearches.add(normalized);
|
|
117
|
-
}
|
|
118
|
-
const synthesis = boundMultilineText(result.synthesisText, MAX_SYNTHESIS_LENGTH);
|
|
119
|
-
if (synthesis)
|
|
120
|
-
deepseekSynthesis = synthesis;
|
|
121
|
-
const providerHits = Array.isArray(result.hits) ? result.hits : [];
|
|
122
|
-
const hitScanLimit = Math.min(providerHits.length, MAX_PROVIDER_HIT_SCAN);
|
|
123
|
-
for (let index = 0; index < hitScanLimit; index++) {
|
|
124
|
-
const rawHit = providerHits[index];
|
|
125
|
-
if (!rawHit)
|
|
126
|
-
continue;
|
|
127
|
-
const hit = normalizeHit(rawHit);
|
|
128
|
-
if (!hit)
|
|
129
|
-
continue;
|
|
130
|
-
const rank = index + 1;
|
|
131
|
-
const existing = candidates.get(hit.url);
|
|
132
|
-
if (!existing) {
|
|
133
|
-
candidates.set(hit.url, { hit, ranks: new Map([[result.source, rank]]) });
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
const previousRank = existing.ranks.get(result.source);
|
|
137
|
-
if (previousRank === undefined || rank < previousRank)
|
|
138
|
-
existing.ranks.set(result.source, rank);
|
|
139
|
-
if (isUrlFallbackTitle(existing.hit.title, existing.hit.url) && !isUrlFallbackTitle(hit.title, hit.url)) {
|
|
140
|
-
existing.hit.title = hit.title;
|
|
141
|
-
}
|
|
142
|
-
if ((!existing.hit.snippet || existing.hit.snippet.length < (hit.snippet?.length ?? 0)) && hit.snippet) {
|
|
143
|
-
existing.hit.snippet = hit.snippet;
|
|
144
|
-
}
|
|
145
|
-
if (!existing.hit.date && hit.date)
|
|
146
|
-
existing.hit.date = hit.date;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const ranked = [...candidates.entries()]
|
|
150
|
-
.sort(([leftUrl, left], [rightUrl, right]) => {
|
|
151
|
-
const scoreDifference = reciprocalRankScore(right) - reciprocalRankScore(left);
|
|
152
|
-
if (scoreDifference !== 0)
|
|
153
|
-
return scoreDifference;
|
|
154
|
-
const rankDifference = bestRank(left) - bestRank(right);
|
|
155
|
-
if (rankDifference !== 0)
|
|
156
|
-
return rankDifference;
|
|
157
|
-
return leftUrl.localeCompare(rightUrl);
|
|
158
|
-
})
|
|
159
|
-
.map(([, candidate]) => ({ ...candidate.hit, sources: [...candidate.ranks.keys()] }))
|
|
160
|
-
.slice(0, MAX_OUTPUT_HITS);
|
|
161
|
-
return {
|
|
162
|
-
hits: ranked,
|
|
163
|
-
relatedSearches: relatedSearches.size > 0 ? [...relatedSearches] : undefined,
|
|
164
|
-
deepseekSynthesis,
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
//# sourceMappingURL=results.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"results.js","sourceRoot":"","sources":["../../../src/extensions/web-search/results.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Result normalization, bounding, deduplication, and ranking for web_search providers.\n */\n\nimport type { ProviderSearchHit, ProviderSearchResult, SearchEngineSource, WebSearchHit } from \"./types.ts\";\n\nexport const MAX_OUTPUT_HITS = 12;\nexport const MAX_QUERY_LENGTH = 500;\nexport const MAX_TITLE_LENGTH = 200;\nexport const MAX_URL_LENGTH = 2048;\nexport const MAX_SNIPPET_LENGTH = 200;\nexport const MAX_DATE_LENGTH = 100;\nexport const MAX_RELATED_SEARCHES = 8;\nexport const MAX_RELATED_SEARCH_LENGTH = 200;\nexport const MAX_SYNTHESIS_LENGTH = 6000;\nexport const MAX_ERROR_MESSAGE_LENGTH = 500;\n/** Provider arrays are transport-bounded too, but avoid scanning an entire hostile payload. */\nexport const MAX_PROVIDER_HIT_SCAN = 200;\nexport const MAX_PROVIDER_RELATED_SCAN = 64;\n/** Historical session details predate the current bounds and may contain oversized arrays. */\nexport const MAX_HISTORICAL_HIT_SCAN = MAX_OUTPUT_HITS * 20;\nexport const MAX_HISTORICAL_SOURCE_SCAN = 32;\nexport const MAX_HISTORICAL_RELATED_SCAN = MAX_RELATED_SEARCHES * 8;\n\nconst RRF_K = 60;\nconst TRACKING_PARAMS = new Set([\n\t\"utm_source\",\n\t\"utm_medium\",\n\t\"utm_campaign\",\n\t\"utm_term\",\n\t\"utm_content\",\n\t\"ref\",\n\t\"fbclid\",\n\t\"gclid\",\n\t\"trk\",\n\t\"gi\",\n]);\n\ninterface FusionCandidate {\n\thit: ProviderSearchHit;\n\tranks: Map<SearchEngineSource, number>;\n}\n\nexport interface FusedSearchResults {\n\thits: WebSearchHit[];\n\trelatedSearches?: string[];\n\tdeepseekSynthesis?: string;\n}\n\nfunction truncateText(text: string, maxLength: number): string {\n\tif (text.length <= maxLength) return text;\n\tif (maxLength <= 3) return text.slice(0, maxLength);\n\treturn `${text.slice(0, maxLength - 3).trimEnd()}...`;\n}\n\n/** Normalize and bound a provider-controlled single-line text field. */\nexport function boundSingleLineText(value: unknown, maxLength: number): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst normalized = value.replace(/\\s+/g, \" \").trim();\n\treturn normalized ? truncateText(normalized, maxLength) : undefined;\n}\n\n/** Trim and bound provider-controlled text that intentionally preserves lines. */\nexport function boundMultilineText(value: unknown, maxLength: number): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst normalized = value.trim();\n\treturn normalized ? truncateText(normalized, maxLength) : undefined;\n}\n\n/** Normalize a usable HTTP(S) source URL without changing non-tracking query values. */\nexport function normalizeUrl(rawUrl: unknown): string | undefined {\n\tif (typeof rawUrl !== \"string\") return undefined;\n\tconst trimmed = rawUrl.trim();\n\tif (!trimmed || trimmed.length > MAX_URL_LENGTH) return undefined;\n\n\ttry {\n\t\tconst url = new URL(trimmed);\n\t\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") return undefined;\n\t\turl.hash = \"\";\n\t\tfor (const parameter of TRACKING_PARAMS) {\n\t\t\tif (url.searchParams.has(parameter)) url.searchParams.delete(parameter);\n\t\t}\n\t\tif (url.pathname.length > 1 && url.pathname.endsWith(\"/\")) {\n\t\t\turl.pathname = url.pathname.replace(/\\/+$/, \"\");\n\t\t}\n\t\tconst normalized = url.toString();\n\t\treturn normalized.length <= MAX_URL_LENGTH ? normalized : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction normalizeHit(hit: ProviderSearchHit): ProviderSearchHit | undefined {\n\tconst url = normalizeUrl(hit.url);\n\tif (!url) return undefined;\n\n\treturn {\n\t\ttitle: boundSingleLineText(hit.title, MAX_TITLE_LENGTH) ?? url,\n\t\turl,\n\t\tsnippet: boundSingleLineText(hit.snippet, MAX_SNIPPET_LENGTH),\n\t\tdate: boundSingleLineText(hit.date, MAX_DATE_LENGTH),\n\t};\n}\n\nfunction isUrlFallbackTitle(title: string, url: string): boolean {\n\tconst normalizedTitle = normalizeUrl(title);\n\treturn normalizedTitle !== undefined && normalizedTitle === normalizeUrl(url);\n}\n\nfunction reciprocalRankScore(candidate: FusionCandidate): number {\n\tlet score = 0;\n\tfor (const rank of candidate.ranks.values()) score += 1 / (RRF_K + rank);\n\treturn score;\n}\n\nfunction bestRank(candidate: FusionCandidate): number {\n\treturn Math.min(...candidate.ranks.values());\n}\n\n/** Bound provider results, deduplicate URLs, and rank them with reciprocal-rank fusion. */\nexport function fuseSearchHits(results: ProviderSearchResult[]): FusedSearchResults {\n\tconst candidates = new Map<string, FusionCandidate>();\n\tconst relatedSearches = new Set<string>();\n\tlet deepseekSynthesis: string | undefined;\n\n\tfor (const result of results) {\n\t\tconst providerRelated = Array.isArray(result.relatedSearches) ? result.relatedSearches : [];\n\t\tconst relatedScanLimit = Math.min(providerRelated.length, MAX_PROVIDER_RELATED_SCAN);\n\t\tfor (let index = 0; index < relatedScanLimit && relatedSearches.size < MAX_RELATED_SEARCHES; index++) {\n\t\t\tconst normalized = boundSingleLineText(providerRelated[index], MAX_RELATED_SEARCH_LENGTH);\n\t\t\tif (normalized) relatedSearches.add(normalized);\n\t\t}\n\t\tconst synthesis = boundMultilineText(result.synthesisText, MAX_SYNTHESIS_LENGTH);\n\t\tif (synthesis) deepseekSynthesis = synthesis;\n\n\t\tconst providerHits = Array.isArray(result.hits) ? result.hits : [];\n\t\tconst hitScanLimit = Math.min(providerHits.length, MAX_PROVIDER_HIT_SCAN);\n\t\tfor (let index = 0; index < hitScanLimit; index++) {\n\t\t\tconst rawHit = providerHits[index];\n\t\t\tif (!rawHit) continue;\n\t\t\tconst hit = normalizeHit(rawHit);\n\t\t\tif (!hit) continue;\n\t\t\tconst rank = index + 1;\n\t\t\tconst existing = candidates.get(hit.url);\n\n\t\t\tif (!existing) {\n\t\t\t\tcandidates.set(hit.url, { hit, ranks: new Map([[result.source, rank]]) });\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst previousRank = existing.ranks.get(result.source);\n\t\t\tif (previousRank === undefined || rank < previousRank) existing.ranks.set(result.source, rank);\n\t\t\tif (isUrlFallbackTitle(existing.hit.title, existing.hit.url) && !isUrlFallbackTitle(hit.title, hit.url)) {\n\t\t\t\texisting.hit.title = hit.title;\n\t\t\t}\n\t\t\tif ((!existing.hit.snippet || existing.hit.snippet.length < (hit.snippet?.length ?? 0)) && hit.snippet) {\n\t\t\t\texisting.hit.snippet = hit.snippet;\n\t\t\t}\n\t\t\tif (!existing.hit.date && hit.date) existing.hit.date = hit.date;\n\t\t}\n\t}\n\n\tconst ranked = [...candidates.entries()]\n\t\t.sort(([leftUrl, left], [rightUrl, right]) => {\n\t\t\tconst scoreDifference = reciprocalRankScore(right) - reciprocalRankScore(left);\n\t\t\tif (scoreDifference !== 0) return scoreDifference;\n\t\t\tconst rankDifference = bestRank(left) - bestRank(right);\n\t\t\tif (rankDifference !== 0) return rankDifference;\n\t\t\treturn leftUrl.localeCompare(rightUrl);\n\t\t})\n\t\t.map(([, candidate]) => ({ ...candidate.hit, sources: [...candidate.ranks.keys()] }))\n\t\t.slice(0, MAX_OUTPUT_HITS);\n\n\treturn {\n\t\thits: ranked,\n\t\trelatedSearches: relatedSearches.size > 0 ? [...relatedSearches] : undefined,\n\t\tdeepseekSynthesis,\n\t};\n}\n"]}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* schema.ts — TypeBox parameter schema and argument normalizer for web_search.
|
|
3
|
-
*/
|
|
4
|
-
import { type Static, Type } from "typebox";
|
|
5
|
-
export declare const WebSearchParamsSchema: Type.TObject<{
|
|
6
|
-
query: Type.TString;
|
|
7
|
-
}>;
|
|
8
|
-
export type WebSearchParams = Static<typeof WebSearchParamsSchema>;
|
|
9
|
-
export declare function normalizeWebSearchParams(raw: unknown): WebSearchParams;
|
|
10
|
-
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/extensions/web-search/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,eAAO,MAAM,qBAAqB;;EAMhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEnE,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,CAuBtE"}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* schema.ts — TypeBox parameter schema and argument normalizer for web_search.
|
|
3
|
-
*/
|
|
4
|
-
import { Type } from "typebox";
|
|
5
|
-
import { MAX_QUERY_LENGTH } from "./results.js";
|
|
6
|
-
export const WebSearchParamsSchema = Type.Object({
|
|
7
|
-
query: Type.String({
|
|
8
|
-
minLength: 1,
|
|
9
|
-
maxLength: MAX_QUERY_LENGTH,
|
|
10
|
-
description: "The search query. Aim for 3-5 keywords; include a year when freshness matters.",
|
|
11
|
-
}),
|
|
12
|
-
});
|
|
13
|
-
export function normalizeWebSearchParams(raw) {
|
|
14
|
-
if (typeof raw === "string") {
|
|
15
|
-
return { query: raw.trim() };
|
|
16
|
-
}
|
|
17
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
18
|
-
return { query: String(raw ?? "").trim() };
|
|
19
|
-
}
|
|
20
|
-
const record = raw;
|
|
21
|
-
let query = "";
|
|
22
|
-
if (typeof record.query === "string") {
|
|
23
|
-
query = record.query.trim();
|
|
24
|
-
}
|
|
25
|
-
else if (typeof record.q === "string") {
|
|
26
|
-
query = record.q.trim();
|
|
27
|
-
}
|
|
28
|
-
else if (typeof record.search_query === "string") {
|
|
29
|
-
query = record.search_query.trim();
|
|
30
|
-
}
|
|
31
|
-
else if (typeof record.prompt === "string") {
|
|
32
|
-
query = record.prompt.trim();
|
|
33
|
-
}
|
|
34
|
-
return { query };
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=schema.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/extensions/web-search/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC,MAAM,CAAC;IAChD,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC;QAClB,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,gBAAgB;QAC3B,WAAW,EAAE,gFAAgF;KAC7F,CAAC;CACF,CAAC,CAAC;AAIH,MAAM,UAAU,wBAAwB,CAAC,GAAY;IACpD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;IAC5C,CAAC;IAED,MAAM,MAAM,GAAG,GAA8B,CAAC;IAE9C,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QACtC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,CAAC;SAAM,IAAI,OAAO,MAAM,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;QACzC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;SAAM,IAAI,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;QACpD,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;IACpC,CAAC;SAAM,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC9C,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,CAAC;AAClB,CAAC","sourcesContent":["/**\n * schema.ts — TypeBox parameter schema and argument normalizer for web_search.\n */\n\nimport { type Static, Type } from \"typebox\";\nimport { MAX_QUERY_LENGTH } from \"./results.ts\";\n\nexport const WebSearchParamsSchema = Type.Object({\n\tquery: Type.String({\n\t\tminLength: 1,\n\t\tmaxLength: MAX_QUERY_LENGTH,\n\t\tdescription: \"The search query. Aim for 3-5 keywords; include a year when freshness matters.\",\n\t}),\n});\n\nexport type WebSearchParams = Static<typeof WebSearchParamsSchema>;\n\nexport function normalizeWebSearchParams(raw: unknown): WebSearchParams {\n\tif (typeof raw === \"string\") {\n\t\treturn { query: raw.trim() };\n\t}\n\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n\t\treturn { query: String(raw ?? \"\").trim() };\n\t}\n\n\tconst record = raw as Record<string, unknown>;\n\n\tlet query = \"\";\n\tif (typeof record.query === \"string\") {\n\t\tquery = record.query.trim();\n\t} else if (typeof record.q === \"string\") {\n\t\tquery = record.q.trim();\n\t} else if (typeof record.search_query === \"string\") {\n\t\tquery = record.search_query.trim();\n\t} else if (typeof record.prompt === \"string\") {\n\t\tquery = record.prompt.trim();\n\t}\n\n\treturn { query };\n}\n"]}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* types.ts — Type definitions for web_search extension providers and fusion engine.
|
|
3
|
-
*/
|
|
4
|
-
export type SearchEngineType = "minimax" | "deepseek" | "dual" | "none";
|
|
5
|
-
export type SearchEngineSource = "MiniMax" | "DeepSeek";
|
|
6
|
-
export interface ProviderSearchHit {
|
|
7
|
-
title: string;
|
|
8
|
-
url: string;
|
|
9
|
-
snippet?: string;
|
|
10
|
-
date?: string;
|
|
11
|
-
}
|
|
12
|
-
export interface WebSearchHit extends ProviderSearchHit {
|
|
13
|
-
sources: SearchEngineSource[];
|
|
14
|
-
}
|
|
15
|
-
export interface WebSearchDetails {
|
|
16
|
-
query: string;
|
|
17
|
-
durationMs: number;
|
|
18
|
-
status: "success" | "error" | "disabled";
|
|
19
|
-
engine: SearchEngineType;
|
|
20
|
-
totalHits: number;
|
|
21
|
-
hits: WebSearchHit[];
|
|
22
|
-
relatedSearches?: string[];
|
|
23
|
-
deepseekSynthesis?: string;
|
|
24
|
-
errorMessage?: string;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* MiniMax search credential. `host` is always present alongside `key` so
|
|
28
|
-
* callers never guard the two separately.
|
|
29
|
-
*/
|
|
30
|
-
export interface MiniMaxSearchCredential {
|
|
31
|
-
key: string;
|
|
32
|
-
host: string;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Resolved credentials: presence of a group means that engine is configured,
|
|
36
|
-
* so impossible states (mode without key, key without host) are unrepresentable.
|
|
37
|
-
* Use `configuredEngine()` from auth.ts to derive the SearchEngineType label.
|
|
38
|
-
*/
|
|
39
|
-
export interface ResolvedSearchCredentials {
|
|
40
|
-
minimax?: MiniMaxSearchCredential;
|
|
41
|
-
deepseek?: {
|
|
42
|
-
key: string;
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
export interface ProviderSearchResult {
|
|
46
|
-
source: SearchEngineSource;
|
|
47
|
-
hits: ProviderSearchHit[];
|
|
48
|
-
relatedSearches?: string[];
|
|
49
|
-
synthesisText?: string;
|
|
50
|
-
}
|
|
51
|
-
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/extensions/web-search/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AACxE,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,UAAU,CAAC;AAExD,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAa,SAAQ,iBAAiB;IACtD,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;IACzC,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACzC,OAAO,CAAC,EAAE,uBAAuB,CAAC;IAClC,QAAQ,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,IAAI,EAAE,iBAAiB,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/extensions/web-search/types.ts"],"names":[],"mappings":"AAAA;;GAEG","sourcesContent":["/**\n * types.ts — Type definitions for web_search extension providers and fusion engine.\n */\n\nexport type SearchEngineType = \"minimax\" | \"deepseek\" | \"dual\" | \"none\";\nexport type SearchEngineSource = \"MiniMax\" | \"DeepSeek\";\n\nexport interface ProviderSearchHit {\n\ttitle: string;\n\turl: string;\n\tsnippet?: string;\n\tdate?: string;\n}\n\nexport interface WebSearchHit extends ProviderSearchHit {\n\tsources: SearchEngineSource[];\n}\n\nexport interface WebSearchDetails {\n\tquery: string;\n\tdurationMs: number;\n\tstatus: \"success\" | \"error\" | \"disabled\";\n\tengine: SearchEngineType;\n\ttotalHits: number;\n\thits: WebSearchHit[];\n\trelatedSearches?: string[];\n\tdeepseekSynthesis?: string;\n\terrorMessage?: string;\n}\n\n/**\n * MiniMax search credential. `host` is always present alongside `key` so\n * callers never guard the two separately.\n */\nexport interface MiniMaxSearchCredential {\n\tkey: string;\n\thost: string;\n}\n\n/**\n * Resolved credentials: presence of a group means that engine is configured,\n * so impossible states (mode without key, key without host) are unrepresentable.\n * Use `configuredEngine()` from auth.ts to derive the SearchEngineType label.\n */\nexport interface ResolvedSearchCredentials {\n\tminimax?: MiniMaxSearchCredential;\n\tdeepseek?: { key: string };\n}\n\nexport interface ProviderSearchResult {\n\tsource: SearchEngineSource;\n\thits: ProviderSearchHit[];\n\trelatedSearches?: string[];\n\tsynthesisText?: string;\n}\n"]}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# Web Search
|
|
2
|
-
|
|
3
|
-
`web_search` is a Pi-native tool for querying live web information through MiniMax and DeepSeek search engines.
|
|
4
|
-
|
|
5
|
-
When both engines are configured, searches run concurrently and results are fused with reciprocal-rank scoring: URLs are normalized (tracking parameters and fragments stripped), duplicates are merged, and high-ranked results from both engines remain represented.
|
|
6
|
-
|
|
7
|
-
| Engine mode | Requirement |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `dual` | Both MiniMax and DeepSeek keys configured |
|
|
10
|
-
| `minimax` | Only a MiniMax key configured |
|
|
11
|
-
| `deepseek` | Only a DeepSeek key configured |
|
|
12
|
-
| `none` | No key found — the tool reports itself disabled |
|
|
13
|
-
|
|
14
|
-
## Credentials
|
|
15
|
-
|
|
16
|
-
Keys are resolved per provider through the runtime's canonical auth chain (`ModelRuntime.getAuth`: runtime API key → `auth.json` → `models.json` → environment). When no runtime is available (or it does not know the provider), the extension falls back to reading `auth.json` directly (provider IDs `minimax-cn`, `minimax`, `deepseek`, including command-configured keys such as `"!op read ..."`) and then the environment variables `MINIMAX_CN_API_KEY`, `MINIMAX_API_KEY`, `DEEPSEEK_API_KEY`.
|
|
17
|
-
|
|
18
|
-
The MiniMax CN account (`minimax-cn`) is preferred over the global one (`minimax`) and selects the `api.minimaxi.com` search host; the global account uses `api.minimax.io`, overridable via `MINIMAX_API_HOST`.
|
|
19
|
-
|
|
20
|
-
Configure with `/login minimax-cn` or `/login deepseek`, or by exporting the environment variables above.
|
|
21
|
-
|
|
22
|
-
When no key is configured, `web_search` is removed from the model's tool set and system prompt entirely — the model never sees or calls it. This is re-evaluated on every session start (`startup`, `/new`, `/reload`, resume, fork). When credentials are available, the extension leaves the host's active-tool set unchanged: normal registration keeps the tool available by default, while an explicit `/tools` or SDK-host disable remains respected until that host enables it again. The tool always stays registered for `/tools` and historical rendering; force-enabling it without keys returns the disabled message.
|
|
23
|
-
|
|
24
|
-
## Usage
|
|
25
|
-
|
|
26
|
-
### Parameters
|
|
27
|
-
|
|
28
|
-
- `query`: the search query, up to 500 characters — 3–5 keywords work best; include a year when freshness matters.
|
|
29
|
-
|
|
30
|
-
### Output
|
|
31
|
-
|
|
32
|
-
The model-facing payload is Markdown containing up to 12 HTTP(S) source results. Titles and snippets are bounded to 200 characters each, source URLs to 2048 characters, DeepSeek synthesis to 6000 characters, and up to 8 related searches to 200 characters each. Results found by both providers are tagged as such; this means the URL appeared in both result sets, not that its claims were independently verified. When structured source URLs are present, the tool result reminds the model to cite the relevant URLs without prescribing a heading or response format.
|
|
33
|
-
|
|
34
|
-
## Limits
|
|
35
|
-
|
|
36
|
-
- With no configured key the tool is hidden from the model (see Credentials); the disabled message only appears when the tool was force-enabled via `/tools` without keys.
|
|
37
|
-
- Engine failures are independent: if one engine errors, the other's results are still returned; the tool errors only when every configured engine fails. Error outcomes are marked as protocol-level tool errors; the credential-disabled warning is not.
|
|
38
|
-
- MiniMax search uses the Coding Plan Search endpoint (`POST /v1/coding_plan/search`), which requires a Coding Plan key — a standard MiniMax API key may be rejected upstream.
|
|
39
|
-
- DeepSeek search goes through the Anthropic-compatible endpoint (`/anthropic/v1/messages`, model `claude-sonnet-search`) with the server-side `web_search_20250305` tool; the request uses `max_tokens: 1024`, followed by the local output bound above. A response must contain a structured `web_search_tool_result`: an empty result array is a valid zero-result search, while text-only, malformed, or structured-error responses count as a provider failure and their synthesis is discarded.
|
|
40
|
-
- Requests time out after 60 seconds (MiniMax) or 90 seconds (DeepSeek) and surface as Pi tool errors. Successful upstream response bodies are limited to 2 MiB, error bodies to 200 bytes, and model-facing error messages to 500 characters.
|
|
41
|
-
|
|
42
|
-
## Implementation notes
|
|
43
|
-
|
|
44
|
-
The extension keeps presentation Pi-native: the call line shows the query, in-flight renders show the engine label with elapsed time past 2s, the collapsed result shows hit count, engines, duration, and a top-domain preview with the configured expand hint, and expanding renders the result sections from `details` — without the model-facing agent directives — falling back to the raw payload for legacy entries.
|
|
45
|
-
|
|
46
|
-
Credential resolution never inspects `getProviderAuthStatus` — that probe returns a truthy `AuthStatus` object even when nothing is configured and carries no key. Only `getAuth` returns usable key material.
|