@code-yeongyu/senpi 2026.10.11 → 2026.10.12
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 +46 -0
- package/dist/bundle/chunks/anthropic-messages-GYG6YZY5.js +10 -0
- package/dist/bundle/chunks/{app-server-command-NHDOL4HQ.js → app-server-command-OL6PPUOA.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-EJF2XJ7Q.js → azure-openai-responses-GU6FOSJR.js} +1 -1
- package/dist/bundle/chunks/{chunk-ZABLYCHT.js → chunk-46JEQXD7.js} +1 -1
- package/dist/bundle/chunks/{chunk-VE3D74HN.js → chunk-55VKYA5V.js} +1 -1
- package/dist/bundle/chunks/{chunk-7UNN3YHW.js → chunk-5AVFHHDF.js} +230 -221
- package/dist/bundle/chunks/{chunk-2JE2DOIF.js → chunk-5DPTM5E2.js} +1 -1
- package/dist/bundle/chunks/chunk-5UPUSGP5.js +2 -0
- package/dist/bundle/chunks/chunk-5VMRMY6N.js +16 -0
- package/dist/bundle/chunks/{chunk-7X3VRAM3.js → chunk-7P3QPVTF.js} +1 -1
- package/dist/bundle/chunks/{chunk-T6IYKWIH.js → chunk-BUGZZVQW.js} +1 -1
- package/dist/bundle/chunks/chunk-DL7EFVT2.js +12 -0
- package/dist/bundle/chunks/chunk-E5YUVGLQ.js +11 -0
- package/dist/bundle/chunks/{chunk-RLFQICEY.js → chunk-EQJY2B5F.js} +1 -1
- package/dist/bundle/chunks/{chunk-VYKBN4MR.js → chunk-GC2RU5TS.js} +1 -1
- package/dist/bundle/chunks/chunk-GPKEJOTQ.js +202 -0
- package/dist/bundle/chunks/{chunk-KCVSSFOV.js → chunk-GQ5PWY6P.js} +4 -3
- package/dist/bundle/chunks/{chunk-4GPJOGXZ.js → chunk-I4AEC6MH.js} +1 -1
- package/dist/bundle/chunks/chunk-JXSFGRBE.js +8 -0
- package/dist/bundle/chunks/{chunk-YGCMN2CX.js → chunk-NAY5LB53.js} +1 -1
- package/dist/bundle/chunks/{chunk-EBOD66AS.js → chunk-PBN2CATL.js} +2 -2
- package/dist/bundle/chunks/chunk-PFNBY43W.js +2 -0
- package/dist/bundle/chunks/{chunk-CY2B4QRR.js → chunk-PUWEQK2W.js} +1 -1
- package/dist/bundle/chunks/{chunk-5DBPUQSX.js → chunk-SF6AUNQZ.js} +1 -1
- package/dist/bundle/chunks/{chunk-G2XAU4BX.js → chunk-TMTT5CLA.js} +1 -1
- package/dist/bundle/chunks/{chunk-2JKDZXIY.js → chunk-VWFKLW73.js} +2 -2
- package/dist/bundle/chunks/chunk-WZMSBRTW.js +2 -0
- package/dist/bundle/chunks/{chunk-55HLKZSB.js → chunk-XVJRRLGN.js} +1 -1
- package/dist/bundle/chunks/chunk-Z2PWWBBD.js +31 -0
- package/dist/bundle/chunks/cli-main-RSIYAR4J.js +3 -0
- package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-SWVU2AXJ.js → cloudflare-workers-ai-system-one-LVWRKOUD.js} +1 -1
- package/dist/bundle/chunks/{google-generative-ai-XG4YX6FQ.js → google-generative-ai-JMGYPTXL.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-BBOZ6OUB.js → google-vertex-CI4FPIU7.js} +1 -1
- package/dist/bundle/chunks/{help-fast-path-EZ3KEW6V.js → help-fast-path-M7KMBM6K.js} +1 -1
- package/dist/bundle/chunks/host-command-6UR3DSFR.js +2 -0
- package/dist/bundle/chunks/host-lifecycle-2BKCCK5X.js +3 -0
- package/dist/bundle/chunks/host-lifecycle.js +10 -7
- package/dist/bundle/chunks/host-session-command-A2MZHEBP.js +19 -0
- package/dist/bundle/chunks/interactive-mode-EJBMTJOH.js +2 -0
- package/dist/bundle/chunks/{list-tips-WE2YGQM6.js → list-tips-BEQAOA4N.js} +1 -1
- package/dist/bundle/chunks/{mistral-conversations-RB3ZBCGE.js → mistral-conversations-5OD7662T.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-V4CUQLV7.js → multi-session-host-YYMLHCUA.js} +4 -4
- package/dist/bundle/chunks/{openai-codex-responses-DBTPUXRW.js → openai-codex-responses-FN3UPAFI.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-QAJQC4BY.js → openai-completions-KMUQ3T4M.js} +1 -1
- package/dist/bundle/chunks/{openai-responses-UBJWCEHG.js → openai-responses-V4Q5GVLO.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-WTRDT4ZH.js → package-manager-cli-6A5ZP26E.js} +1 -1
- package/dist/bundle/chunks/rotation-stream-PT6LLBMJ.js +2 -0
- package/dist/bundle/chunks/rpc-mode-XNYJPYUM.js +2 -0
- package/dist/bundle/chunks/runtime-session-ZBHFMT65.js +2 -0
- package/dist/bundle/chunks/{schedule-command-PJVRKAKD.js → schedule-command-FYQG2MFX.js} +1 -1
- package/dist/bundle/chunks/session-control-endpoint-7TX4XHN4.js +3 -0
- package/dist/bundle/chunks/session-picker-4RNB27SM.js +2 -0
- package/dist/bundle/chunks/session-worker.js +418 -412
- package/dist/bundle/chunks/{typesafe-system-one-B5TW3FHM.js → typesafe-system-one-WUHW7HR4.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/bundle/runtime-manifest.json +1 -1
- package/dist/core/agent-session.d.ts +11 -2
- package/dist/core/agent-session.js +152 -43
- package/dist/core/compaction/compaction.js +2 -0
- package/dist/core/extensions/builtin/anthropic-web-search/index.js +22 -14
- package/dist/core/extensions/builtin/cache-keepalive/index.js +8 -4
- package/dist/core/extensions/builtin/cache-keepalive/session-prewarm.d.ts +2 -1
- package/dist/core/extensions/builtin/cache-keepalive/session-prewarm.js +55 -7
- package/dist/core/extensions/builtin/cache-keepalive/startup-activity-gate.d.ts +8 -0
- package/dist/core/extensions/builtin/cache-keepalive/startup-activity-gate.js +25 -0
- package/dist/core/extensions/builtin/compaction/index.js +13 -5
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +1 -0
- package/dist/core/extensions/builtin/compaction/speculative.js +8 -4
- package/dist/core/extensions/builtin/moved-path-guard/tool-classes.js +1 -0
- package/dist/core/extensions/builtin/openai-web-search/index.d.ts +4 -1
- package/dist/core/extensions/builtin/openai-web-search/index.js +54 -17
- package/dist/core/extensions/builtin/server-search-fallback.d.ts +12 -0
- package/dist/core/extensions/builtin/server-search-fallback.js +50 -0
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +10 -1
- package/dist/core/extensions/builtin/terminal/runtime-session.js +48 -4
- package/dist/core/extensions/builtin/websearch/index.d.ts +1 -1
- package/dist/core/extensions/builtin/websearch/index.js +119 -18
- package/dist/core/extensions/builtin/websearch/server-search.d.ts +11 -0
- package/dist/core/extensions/builtin/websearch/server-search.js +230 -0
- package/dist/core/extensions/builtin/websearch/websearch/native.d.ts +2 -0
- package/dist/core/extensions/builtin/websearch/websearch/search-model.js +15 -0
- package/dist/core/extensions/runner.d.ts +8 -1
- package/dist/core/extensions/runner.js +56 -7
- package/dist/core/extensions/types.d.ts +12 -2
- package/dist/core/extensions/user-activity.d.ts +10 -0
- package/dist/core/extensions/user-activity.js +20 -0
- package/dist/core/model-config-schema.d.ts +34 -0
- package/dist/core/model-config-schema.js +2 -0
- package/dist/core/model-config.js +1 -0
- package/dist/core/reserved-keywords.d.ts +28 -0
- package/dist/core/reserved-keywords.js +81 -0
- package/dist/core/retry-fallback/candidates.d.ts +1 -1
- package/dist/core/retry-fallback/candidates.js +1 -12
- package/dist/core/retry-fallback/controller.d.ts +3 -1
- package/dist/core/retry-fallback/controller.js +11 -5
- package/dist/core/retry-fallback/cooldown.d.ts +2 -1
- package/dist/core/retry-fallback/cooldown.js +21 -12
- package/dist/core/retry-fallback/unusable.d.ts +2 -0
- package/dist/core/retry-fallback/unusable.js +14 -2
- package/dist/core/retry-fallback/usage-limit.d.ts +10 -1
- package/dist/core/retry-fallback/usage-limit.js +39 -2
- package/dist/core/session-title-generator.js +2 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/modes/index.d.ts +1 -1
- package/dist/modes/interactive/components/assistant-render-descriptors.js +7 -1
- package/dist/modes/interactive/composer-user-activity.d.ts +6 -0
- package/dist/modes/interactive/composer-user-activity.js +30 -0
- package/dist/modes/interactive/grok/chrome.js +2 -1
- package/dist/modes/interactive/interactive-mode.js +15 -6
- package/dist/modes/interactive/session-control-registry.js +8 -1
- package/dist/modes/interactive/theme/reserved-keyword-rainbow.d.ts +11 -0
- package/dist/modes/interactive/theme/reserved-keyword-rainbow.js +50 -0
- package/dist/modes/interactive/theme/theme.d.ts +3 -1
- package/dist/modes/interactive/theme/theme.js +9 -0
- package/dist/modes/print-mode.js +7 -2
- package/dist/modes/rpc/connection-handler.js +43 -11
- package/dist/modes/rpc/custom-capability.d.ts +2 -0
- package/dist/modes/rpc/custom-capability.js +2 -0
- package/dist/modes/rpc/host-admission-proxy.d.ts +9 -0
- package/dist/modes/rpc/host-admission-proxy.js +211 -0
- package/dist/modes/rpc/host-admission.d.ts +21 -0
- package/dist/modes/rpc/host-admission.js +59 -0
- package/dist/modes/rpc/host-capabilities.js +2 -1
- package/dist/modes/rpc/host-client-occupancy.d.ts +2 -1
- package/dist/modes/rpc/host-client-occupancy.js +7 -0
- package/dist/modes/rpc/host-decision.d.ts +2 -2
- package/dist/modes/rpc/host-decision.js +4 -0
- package/dist/modes/rpc/host-ensure-types.d.ts +2 -0
- package/dist/modes/rpc/host-ensure.js +31 -3
- package/dist/modes/rpc/host-lifecycle-drain.d.ts +2 -1
- package/dist/modes/rpc/host-lifecycle-drain.js +3 -1
- package/dist/modes/rpc/host-lifecycle-proxy.d.ts +3 -2
- package/dist/modes/rpc/host-lifecycle-proxy.js +10 -19
- package/dist/modes/rpc/host-lifecycle-shutdown.d.ts +2 -0
- package/dist/modes/rpc/host-lifecycle-shutdown.js +3 -1
- package/dist/modes/rpc/host-lifecycle-ticker.d.ts +11 -0
- package/dist/modes/rpc/host-lifecycle-ticker.js +27 -0
- package/dist/modes/rpc/host-lifecycle.js +15 -23
- package/dist/modes/rpc/host-outcome.js +1 -0
- package/dist/modes/rpc/host-protocol-info.d.ts +2 -0
- package/dist/modes/rpc/host-protocol-info.js +1 -0
- package/dist/modes/rpc/host-session-runner.js +22 -1
- package/dist/modes/rpc/host-status-all.js +1 -0
- package/dist/modes/rpc/host-status.d.ts +1 -0
- package/dist/modes/rpc/host-status.js +5 -1
- package/dist/modes/rpc/rpc-client.d.ts +7 -1
- package/dist/modes/rpc/rpc-client.js +12 -0
- package/dist/modes/rpc/rpc-types.d.ts +49 -1
- package/dist/modes/rpc/rpc-types.js +5 -0
- package/dist/modes/rpc/session-command-activity.js +2 -0
- package/dist/modes/rpc/session-held.js +3 -0
- package/docs/extensions.md +13 -1
- package/docs/providers.md +88 -0
- package/docs/rpc.md +150 -5
- package/docs/web-search.md +3 -1
- package/package.json +7 -7
- package/dist/bundle/chunks/anthropic-messages-5QQJVQPZ.js +0 -9
- package/dist/bundle/chunks/chunk-2A3MS2Z7.js +0 -8
- package/dist/bundle/chunks/chunk-6SBY4ZWC.js +0 -2
- package/dist/bundle/chunks/chunk-6WCOSBI7.js +0 -2
- package/dist/bundle/chunks/chunk-E75RO54O.js +0 -14
- package/dist/bundle/chunks/chunk-JMYO34RK.js +0 -2
- package/dist/bundle/chunks/chunk-KRNXUTZJ.js +0 -2
- package/dist/bundle/chunks/chunk-L4HVJWIF.js +0 -11
- package/dist/bundle/chunks/chunk-N5WLLHUE.js +0 -2
- package/dist/bundle/chunks/chunk-NEFNNQSV.js +0 -9
- package/dist/bundle/chunks/chunk-PWIYVLIA.js +0 -9
- package/dist/bundle/chunks/chunk-Q3R44CGT.js +0 -5
- package/dist/bundle/chunks/chunk-QIARZN7G.js +0 -31
- package/dist/bundle/chunks/chunk-QKU6JOA4.js +0 -2
- package/dist/bundle/chunks/chunk-QYWXDE47.js +0 -2
- package/dist/bundle/chunks/chunk-XHELSLN3.js +0 -188
- package/dist/bundle/chunks/chunk-YDJ4HGWO.js +0 -16
- package/dist/bundle/chunks/chunk-ZJHRDQCH.js +0 -2
- package/dist/bundle/chunks/cli-main-TUBNBZNK.js +0 -3
- package/dist/bundle/chunks/host-command-WO7VKJBJ.js +0 -2
- package/dist/bundle/chunks/host-lifecycle-X2J5FTJL.js +0 -3
- package/dist/bundle/chunks/host-session-command-ICBOH5RP.js +0 -19
- package/dist/bundle/chunks/interactive-mode-UGDNCGQ5.js +0 -2
- package/dist/bundle/chunks/rotation-stream-OODURUGZ.js +0 -2
- package/dist/bundle/chunks/rpc-mode-22MCT32O.js +0 -2
- package/dist/bundle/chunks/runtime-session-I4NDNGC5.js +0 -2
- package/dist/bundle/chunks/session-control-endpoint-SFPRQBDO.js +0 -3
- package/dist/bundle/chunks/session-picker-3ZQPV7Z3.js +0 -2
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { isAnthropicWebSearchEnabled, supportsNativeAnthropicWebSearch } from "../anthropic-web-search/index.js";
|
|
2
|
+
import { isOpenaiWebSearchEnabled, supportsNativeOpenAiWebSearch } from "../openai-web-search/index.js";
|
|
3
|
+
import { isServerSearchDisabled, isServerSearchFallback, SERVER_SEARCH_FALLBACK } from "../server-search-fallback.js";
|
|
4
|
+
function isRecord(value) {
|
|
5
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
export function additionalServerSearch(model) {
|
|
8
|
+
if (!model)
|
|
9
|
+
return undefined;
|
|
10
|
+
const declared = model.compat && "supportsWebSearch" in model.compat ? model.compat.supportsWebSearch : undefined;
|
|
11
|
+
if (declared !== true)
|
|
12
|
+
return undefined;
|
|
13
|
+
// Google Search grounding uses GenerateContent config.tools, not Messages/Responses.
|
|
14
|
+
// Gemini 2/3 document this native tool, but search mixed with function tools
|
|
15
|
+
// remains opt-in until a live endpoint probe succeeds.
|
|
16
|
+
// https://ai.google.dev/gemini-api/docs/google-search
|
|
17
|
+
// https://github.com/googleapis/js-genai/blob/main/codegen_instructions.md
|
|
18
|
+
if ((model.api === "google-generative-ai" || model.api === "google-vertex") &&
|
|
19
|
+
/^gemini-(?:2[.-]|3[.-]|flash-latest|pro-latest)/.test(model.id) &&
|
|
20
|
+
!/(image|live|tts|embedding|computer-use)/.test(model.id)) {
|
|
21
|
+
return "google";
|
|
22
|
+
}
|
|
23
|
+
// OpenRouter's own server tool works on Chat Completions and Responses.
|
|
24
|
+
// Do not translate it into the upstream vendor's tool shape.
|
|
25
|
+
// https://openrouter.ai/docs/guides/features/server-tools/web-search
|
|
26
|
+
if (model.provider === "openrouter" && (model.api === "openai-completions" || model.api === "openai-responses")) {
|
|
27
|
+
return "openrouter";
|
|
28
|
+
}
|
|
29
|
+
// PAYG Moonshot executes $web_search and returns its result in generated
|
|
30
|
+
// arguments; the client echoes those arguments as a tool result, without
|
|
31
|
+
// making another search request. This is NOT the Kimi coding-plan endpoint.
|
|
32
|
+
// https://platform.kimi.ai/docs/guide/use-web-search
|
|
33
|
+
if (model.api === "openai-completions" && (model.provider === "moonshotai" || model.provider === "moonshotai-cn")) {
|
|
34
|
+
return "moonshot";
|
|
35
|
+
}
|
|
36
|
+
// The same provider id can point at PAYG chat or the coding-plan endpoint.
|
|
37
|
+
// Only an explicit per-route flag enables the PAYG in-chat server tool.
|
|
38
|
+
// https://docs.z.ai/guides/tools/web-search
|
|
39
|
+
// https://docs.z.ai/devpack/mcp/search-mcp-server
|
|
40
|
+
if (model.api === "openai-completions" &&
|
|
41
|
+
(model.provider === "zai" || model.provider === "z-ai") &&
|
|
42
|
+
declared === true) {
|
|
43
|
+
return "zai";
|
|
44
|
+
}
|
|
45
|
+
// Sonar searches inside the main completion without a tools[] declaration.
|
|
46
|
+
// Synchronous Sonar calls are now reformulated as Agent API calls upstream.
|
|
47
|
+
// https://docs.perplexity.ai/docs/sonar/quickstart
|
|
48
|
+
if (model.provider === "perplexity" && model.api === "openai-completions" && /^sonar/.test(model.id)) {
|
|
49
|
+
return "perplexity";
|
|
50
|
+
}
|
|
51
|
+
// DeepSeek documents search on /anthropic, not the default Chat Completions API.
|
|
52
|
+
// An Anthropic-format model opts in through compat.supportsWebSearch, including replay.
|
|
53
|
+
// https://api-docs.deepseek.com/quick_start/agent_integrations/claude_code
|
|
54
|
+
// Kimi coding-plan docs do not specify a search/replay contract. Keep the explicit
|
|
55
|
+
// Messages compat opt-in; do not confuse it with PAYG's deprecated $web_search.
|
|
56
|
+
// https://www.kimi.com/code/docs/en/third-party-tools/claude-code
|
|
57
|
+
// https://platform.kimi.ai/docs/guide/use-web-search
|
|
58
|
+
// GLM coding-plan search is documented as webSearchPrime over remote MCP, not
|
|
59
|
+
// the PAYG chat tool. Do not inject the PAYG tool on the coding endpoint.
|
|
60
|
+
// https://docs.z.ai/devpack/mcp/search-mcp-server
|
|
61
|
+
// https://docs.z.ai/guides/tools/web-search
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
export function hasServerSearch(model) {
|
|
65
|
+
if (!model)
|
|
66
|
+
return false;
|
|
67
|
+
return ((supportsNativeAnthropicWebSearch(model) && isAnthropicWebSearchEnabled()) ||
|
|
68
|
+
(supportsNativeOpenAiWebSearch(model) && isOpenaiWebSearchEnabled()) ||
|
|
69
|
+
additionalServerSearch(model) !== undefined);
|
|
70
|
+
}
|
|
71
|
+
function isMoonshotSearchTool(tool) {
|
|
72
|
+
return (isRecord(tool) &&
|
|
73
|
+
(tool.name === "$web_search" || (isRecord(tool.function) && tool.function.name === "$web_search")));
|
|
74
|
+
}
|
|
75
|
+
function isClientSearchTool(tool) {
|
|
76
|
+
return (isRecord(tool) &&
|
|
77
|
+
(tool.type === "function" || "input_schema" in tool) &&
|
|
78
|
+
(tool.name === "web_search" || (isRecord(tool.function) && tool.function.name === "web_search")));
|
|
79
|
+
}
|
|
80
|
+
function withTools(payload, tools) {
|
|
81
|
+
const result = { ...payload };
|
|
82
|
+
if (tools.length)
|
|
83
|
+
result.tools = tools;
|
|
84
|
+
else
|
|
85
|
+
delete result.tools;
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
function isSearchTool(tool) {
|
|
89
|
+
if (!isRecord(tool))
|
|
90
|
+
return false;
|
|
91
|
+
return (tool.name === "web_search" ||
|
|
92
|
+
isMoonshotSearchTool(tool) ||
|
|
93
|
+
(isRecord(tool.function) && tool.function.name === "web_search") ||
|
|
94
|
+
(typeof tool.type === "string" &&
|
|
95
|
+
(tool.type === "openrouter:web_search" || tool.type === "web_search" || tool.type.startsWith("web_search_"))));
|
|
96
|
+
}
|
|
97
|
+
function googleTools(tools, retainFunction, disabled) {
|
|
98
|
+
const result = [];
|
|
99
|
+
for (const tool of tools) {
|
|
100
|
+
if (!isRecord(tool) || "googleSearch" in tool || "google_search" in tool)
|
|
101
|
+
continue;
|
|
102
|
+
if (!Array.isArray(tool.functionDeclarations)) {
|
|
103
|
+
result.push(tool);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const declarations = tool.functionDeclarations.filter((declaration) => !isRecord(declaration) || retainFunction || declaration.name !== "web_search");
|
|
107
|
+
if (declarations.length)
|
|
108
|
+
result.push({ ...tool, functionDeclarations: declarations });
|
|
109
|
+
}
|
|
110
|
+
if (!retainFunction && !disabled)
|
|
111
|
+
result.push({ googleSearch: {} });
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
/** Preserve adapter-built function search on fallback; never reconstruct its normalized schema. */
|
|
115
|
+
export function serverSearchPayload(model, payload, failed = false) {
|
|
116
|
+
if (!isRecord(payload))
|
|
117
|
+
return payload;
|
|
118
|
+
const disabled = isServerSearchDisabled(payload);
|
|
119
|
+
const fallback = failed || isServerSearchFallback(payload);
|
|
120
|
+
if (additionalServerSearch(model) !== "moonshot") {
|
|
121
|
+
if (isMoonshotSearchTool(payload.tool_choice)) {
|
|
122
|
+
const { tool_choice: _choice, ...rest } = payload;
|
|
123
|
+
payload = rest;
|
|
124
|
+
}
|
|
125
|
+
if (!isRecord(payload))
|
|
126
|
+
return payload;
|
|
127
|
+
if (Array.isArray(payload.tools)) {
|
|
128
|
+
const tools = payload.tools.filter((tool) => !isMoonshotSearchTool(tool));
|
|
129
|
+
if (tools.length !== payload.tools.length)
|
|
130
|
+
payload = withTools(payload, tools);
|
|
131
|
+
}
|
|
132
|
+
if (isRecord(payload) && isRecord(payload.config) && Array.isArray(payload.config.tools)) {
|
|
133
|
+
payload = {
|
|
134
|
+
...payload,
|
|
135
|
+
config: withTools(payload.config, payload.config.tools.flatMap((tool) => {
|
|
136
|
+
if (!isRecord(tool) || !Array.isArray(tool.functionDeclarations))
|
|
137
|
+
return [tool];
|
|
138
|
+
const declarations = tool.functionDeclarations.filter((declaration) => !isMoonshotSearchTool(declaration));
|
|
139
|
+
return declarations.length ? [{ ...tool, functionDeclarations: declarations }] : [];
|
|
140
|
+
})),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (!model || !isRecord(payload))
|
|
145
|
+
return payload;
|
|
146
|
+
const google = model.api === "google-generative-ai" || model.api === "google-vertex";
|
|
147
|
+
if (google && (additionalServerSearch(model) === "google" || fallback || disabled)) {
|
|
148
|
+
const config = isRecord(payload.config) ? payload.config : {};
|
|
149
|
+
const tools = Array.isArray(config.tools) ? config.tools : [];
|
|
150
|
+
return {
|
|
151
|
+
...payload,
|
|
152
|
+
config: withTools(config, googleTools(tools, fallback || disabled, disabled)),
|
|
153
|
+
...(fallback ? { [SERVER_SEARCH_FALLBACK]: true } : {}),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
const kind = additionalServerSearch(model);
|
|
157
|
+
if (!fallback && !kind && !disabled)
|
|
158
|
+
return payload;
|
|
159
|
+
const tools = (Array.isArray(payload.tools) ? payload.tools : []).filter((tool) => {
|
|
160
|
+
if (!isSearchTool(tool))
|
|
161
|
+
return true;
|
|
162
|
+
if (!disabled && !fallback)
|
|
163
|
+
return false;
|
|
164
|
+
// Responses/Completions use type:function; Messages uses input_schema.
|
|
165
|
+
// These declarations already came through their provider's schema builder.
|
|
166
|
+
return isClientSearchTool(tool);
|
|
167
|
+
});
|
|
168
|
+
if (!fallback && !disabled && kind === "openrouter") {
|
|
169
|
+
tools.push({ type: "openrouter:web_search" });
|
|
170
|
+
}
|
|
171
|
+
else if (!fallback && !disabled && kind === "moonshot") {
|
|
172
|
+
tools.push({ type: "builtin_function", function: { name: "$web_search" } });
|
|
173
|
+
}
|
|
174
|
+
else if (!fallback && !disabled && kind === "zai") {
|
|
175
|
+
tools.push({ type: "web_search", web_search: { enable: true, search_result: true } });
|
|
176
|
+
}
|
|
177
|
+
const result = withTools(payload, tools);
|
|
178
|
+
if (fallback || disabled) {
|
|
179
|
+
// An include or tool_choice targeting the removed server tool would reject the retry.
|
|
180
|
+
if (Array.isArray(result.include)) {
|
|
181
|
+
result.include = result.include.filter((item) => item !== "web_search_call.action.sources");
|
|
182
|
+
}
|
|
183
|
+
if (isRecord(result.tool_choice) &&
|
|
184
|
+
isSearchTool(result.tool_choice) &&
|
|
185
|
+
!isClientSearchTool(result.tool_choice) &&
|
|
186
|
+
!(result.tool_choice.name === "web_search" && tools.some(isClientSearchTool)))
|
|
187
|
+
delete result.tool_choice;
|
|
188
|
+
}
|
|
189
|
+
return fallback ? { ...result, [SERVER_SEARCH_FALLBACK]: true } : result;
|
|
190
|
+
}
|
|
191
|
+
/** Only search-specific errors trigger fallback; cancellation and unrelated provider failures do not. */
|
|
192
|
+
export function serverSearchFailure(message, model) {
|
|
193
|
+
if (message.stopReason === "aborted")
|
|
194
|
+
return undefined;
|
|
195
|
+
// Sonar has inherent retrieval, not an independent server tool declaration or
|
|
196
|
+
// tool-result error contract. Its model errors stay with core retry; never
|
|
197
|
+
// turn an arbitrary Sonar error into an unsupported function-tool request.
|
|
198
|
+
if (model?.provider === "perplexity" && model.api === "openai-completions" && /^sonar/.test(model.id))
|
|
199
|
+
return undefined;
|
|
200
|
+
for (const block of message.content) {
|
|
201
|
+
if (block.type !== "providerNative" || !isRecord(block.raw))
|
|
202
|
+
continue;
|
|
203
|
+
const raw = block.raw;
|
|
204
|
+
if (raw.type === "web_search_call" && raw.status === "failed") {
|
|
205
|
+
return "server search result: failed";
|
|
206
|
+
}
|
|
207
|
+
if (raw.type !== "web_search_tool_result" || !isRecord(raw.content))
|
|
208
|
+
continue;
|
|
209
|
+
if (raw.content.type === "web_search_tool_result_error" && typeof raw.content.error_code === "string") {
|
|
210
|
+
return `server search result: ${raw.content.error_code.replace(/[^a-z_]/g, "").slice(0, 60)}`;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (message.stopReason === "error" &&
|
|
214
|
+
/(\b401\b|invalid[_ -]?(?:api[_ -]?)?key|authentication|unauthorized|quota|billing|insufficient)/i.test(message.errorMessage ?? "")) {
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
if (message.stopReason === "error" &&
|
|
218
|
+
model !== undefined &&
|
|
219
|
+
(model.api === "google-generative-ai" || model.api === "google-vertex") &&
|
|
220
|
+
/(multiple tools|combining.*tools|tools.*combination|tool use with function calling is unsupported)/i.test(message.errorMessage ?? "")) {
|
|
221
|
+
return "server search request rejected (mixed tools unsupported)";
|
|
222
|
+
}
|
|
223
|
+
if (message.stopReason === "error" &&
|
|
224
|
+
/(web_search_\d{8}|web_search_preview|openrouter:web_search|googleSearch|google_search|(?:tool(?:[_ -]?type)?|type)\s*[:=]?\s*["']?web_search\b)/i.test(message.errorMessage ?? "")) {
|
|
225
|
+
const status = message.errorMessage?.match(/\b(400|403|429|500|502|503)\b/)?.[1];
|
|
226
|
+
return `server search request rejected${status ? ` (HTTP ${status})` : ""}`;
|
|
227
|
+
}
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=server-search.js.map
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
1
2
|
import type { SearchProvider, SearchProviderEntry } from "./types.ts";
|
|
2
3
|
export interface NativeModelInfo {
|
|
3
4
|
provider: string;
|
|
4
5
|
id: string;
|
|
5
6
|
baseUrl: string;
|
|
6
7
|
api?: string;
|
|
8
|
+
compat?: Model<Api>["compat"];
|
|
7
9
|
cost?: {
|
|
8
10
|
input: number;
|
|
9
11
|
output: number;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { hasServerSearch } from "../server-search.js";
|
|
1
2
|
import { nativeMapping, nativeRouteKey } from "./native.js";
|
|
2
3
|
export const SESSION_SEARCH_MODEL = "session";
|
|
3
4
|
// Cheaper same-provider models for hosted search, after oh-my-pi's per-provider `web-search-model` catalog axis.
|
|
@@ -40,6 +41,20 @@ function defaultChoice(session, candidates) {
|
|
|
40
41
|
export function resolveNativeSearchModel(session, registry, setting) {
|
|
41
42
|
if (!session || !nativeRouteKey(session))
|
|
42
43
|
return undefined;
|
|
44
|
+
// Main-request server search is always the active model's job. If that fails,
|
|
45
|
+
// the standalone retry also keeps that model; only no-server routes default
|
|
46
|
+
// to the cheaper auxiliary model below. An auxiliary setting cannot preempt
|
|
47
|
+
// the in-turn tool. See senpi#3122.
|
|
48
|
+
if (session.api !== undefined &&
|
|
49
|
+
hasServerSearch({
|
|
50
|
+
api: session.api,
|
|
51
|
+
provider: session.provider,
|
|
52
|
+
id: session.id,
|
|
53
|
+
baseUrl: session.baseUrl,
|
|
54
|
+
compat: session.compat,
|
|
55
|
+
})) {
|
|
56
|
+
return { model: session.id, source: "session" };
|
|
57
|
+
}
|
|
43
58
|
if (setting === SESSION_SEARCH_MODEL)
|
|
44
59
|
return { model: session.id, source: "session" };
|
|
45
60
|
const candidates = sameRouteModels(session, registry);
|
|
@@ -14,6 +14,9 @@ import type { SessionManager } from "../session-manager.ts";
|
|
|
14
14
|
import type { BuildSystemPromptOptions } from "../system-prompt.ts";
|
|
15
15
|
import type { VirtualModelDefinition } from "../virtual-models.ts";
|
|
16
16
|
import type { AgentBeforeSettleEvent, BeforeAgentStartEvent, BeforeAgentStartEventResult, BeforeProviderHeadersEvent, BeforeProviderRequestEvent, BoundaryContextPreview, ContextEvent, ContextWithSystemEvent, EntryRenderer, EntryRendererOptions, Extension, ExtensionActions, ExtensionCommandContext, ExtensionCommandContextActions, ExtensionContext, ExtensionContextActions, ExtensionError, ExtensionEvent, ExtensionFlag, ExtensionMode, ExtensionRuntime, ExtensionShortcut, ExtensionToolContext, ExtensionUIContext, InputEvent, InputEventResult, InputSource, LoadExtensionsResult, MarkdownTransformer, MessageEndEvent, MessageRenderer, ModelSelectEvent, ModelSelectEventResult, ProjectTrustContext, ProjectTrustEvent, ProjectTrustEventResult, ProviderConfig, ProviderRequestPreparation, RegisteredMcpServerDeclaration, RegisteredTool, ReplacedSessionContext, ResolvedCommand, ResourcesDiscoverEvent, SessionBeforeCompactResult, SessionBeforeForkResult, SessionBeforeReloadResult, SessionBeforeSwitchResult, SessionBeforeTreeResult, SessionBoundaryDraft, SessionShutdownEvent, ToolCallEvent, ToolCallEventResult, ToolResultEvent, ToolResultEventResult, TurnEndEvent, UserBashEvent, UserBashEventResult } from "./types.ts";
|
|
17
|
+
export declare class ExtensionRpcRequestNotFoundError extends Error {
|
|
18
|
+
constructor(name: string);
|
|
19
|
+
}
|
|
17
20
|
/** Combined result from all before_agent_start handlers */
|
|
18
21
|
interface BeforeAgentStartCombinedResult {
|
|
19
22
|
messages?: NonNullable<BeforeAgentStartEventResult["message"]>[];
|
|
@@ -132,6 +135,7 @@ export declare class ExtensionRunner {
|
|
|
132
135
|
private isCompactingFn;
|
|
133
136
|
private checkReloadVetoFn;
|
|
134
137
|
private getContextUsageFn;
|
|
138
|
+
private getCompactionModelFn;
|
|
135
139
|
private getCompactionSettingsFn;
|
|
136
140
|
private getPromptCacheSafeWaitSecondsFn;
|
|
137
141
|
private getPromptCacheGoalBackstopMaxSecondsFn;
|
|
@@ -151,6 +155,7 @@ export declare class ExtensionRunner {
|
|
|
151
155
|
private getLoadedHookSourcesFn;
|
|
152
156
|
private getSystemPromptOptionsFn;
|
|
153
157
|
private getPromptCachePrefixRequestFn;
|
|
158
|
+
private onUserActivityFn;
|
|
154
159
|
private getAgentDirFn;
|
|
155
160
|
private executeToolFn;
|
|
156
161
|
private getCallableToolsFn;
|
|
@@ -289,7 +294,9 @@ export declare class ExtensionRunner {
|
|
|
289
294
|
* handlers then see the full transcript and their output is used as returned.
|
|
290
295
|
*/
|
|
291
296
|
emitContext(messages: AgentMessage[], excludeExtensionPath?: string, source?: ContextEvent["source"]): Promise<AgentMessage[]>;
|
|
292
|
-
prepareProviderRequest(messages: AgentMessage[], excludeExtensionPath?: string
|
|
297
|
+
prepareProviderRequest(messages: AgentMessage[], excludeExtensionPath?: string, options?: {
|
|
298
|
+
allowServerSearch?: boolean;
|
|
299
|
+
}): Promise<ProviderRequestPreparation>;
|
|
293
300
|
emitBeforeProviderRequest(payload: unknown, excludeExtensionPath?: string, request?: {
|
|
294
301
|
model: Model<Api>;
|
|
295
302
|
headers: ProviderHeaders;
|
|
@@ -9,11 +9,18 @@ import { createEventBus, EXTENSION_RPC_EVENT_CHANNEL } from "../event-bus.js";
|
|
|
9
9
|
import { DEFAULT_SESSION_SHUTDOWN_HANDLER_TIMEOUT_MS, DEFAULT_SESSION_SHUTDOWN_HANDLER_WARN_MS, SettingsManager, } from "../settings-manager.js";
|
|
10
10
|
import { goalFilePath } from "./builtin/goal/persistence.js";
|
|
11
11
|
import { goalStoreRef } from "./builtin/goal/store-ref.js";
|
|
12
|
+
import { disableServerSearch } from "./builtin/server-search-fallback.js";
|
|
12
13
|
import { dispatchContextMessages } from "./context-dispatch.js";
|
|
13
14
|
import { kernelToolsStorage } from "./kernel-tools-context.js";
|
|
14
15
|
import { drainPendingProviderRegistrations } from "./loader.js";
|
|
15
16
|
import { SessionStartTurnGate } from "./session-start-turn-gate.js";
|
|
16
17
|
import { RUNTIME_EXTENSION_PATH } from "./types.js";
|
|
18
|
+
export class ExtensionRpcRequestNotFoundError extends Error {
|
|
19
|
+
constructor(name) {
|
|
20
|
+
super(`Unknown extension RPC request: ${name}`);
|
|
21
|
+
this.name = "ExtensionRpcRequestNotFoundError";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
17
24
|
// Extension shortcuts compete with canonical keybinding ids from keybindings.json.
|
|
18
25
|
// Only editor-global shortcuts are reserved here. Picker-specific bindings are not.
|
|
19
26
|
const RESERVED_KEYBINDINGS_FOR_EXTENSION_CONFLICTS = [
|
|
@@ -323,6 +330,7 @@ export class ExtensionRunner {
|
|
|
323
330
|
this.shutdownHandler = contextActions.shutdown;
|
|
324
331
|
this.getContextUsageFn = contextActions.getContextUsage;
|
|
325
332
|
this.getCompactionSettingsFn = contextActions.getCompactionSettings;
|
|
333
|
+
this.getCompactionModelFn = contextActions.getCompactionModel;
|
|
326
334
|
if (contextActions.getPromptCacheSafeWaitSeconds)
|
|
327
335
|
this.getPromptCacheSafeWaitSecondsFn = contextActions.getPromptCacheSafeWaitSeconds;
|
|
328
336
|
if (contextActions.getPromptCacheGoalBackstopMaxSeconds)
|
|
@@ -348,6 +356,7 @@ export class ExtensionRunner {
|
|
|
348
356
|
this.getAgentDirFn = contextActions.getAgentDir;
|
|
349
357
|
this.getSystemPromptOptionsFn = contextActions.getSystemPromptOptions ?? (() => ({ cwd: this.cwd }));
|
|
350
358
|
this.getPromptCachePrefixRequestFn = contextActions.getPromptCachePrefixRequest;
|
|
359
|
+
this.onUserActivityFn = contextActions.onUserActivity;
|
|
351
360
|
this.executeToolFn = contextActions.executeTool;
|
|
352
361
|
this.getCallableToolsFn = contextActions.getCallableTools ?? (() => []);
|
|
353
362
|
for (const extension of this.extensions) {
|
|
@@ -826,7 +835,7 @@ export class ExtensionRunner {
|
|
|
826
835
|
return handler === undefined ? [] : [handler];
|
|
827
836
|
});
|
|
828
837
|
if (matches.length === 0) {
|
|
829
|
-
throw new
|
|
838
|
+
throw new ExtensionRpcRequestNotFoundError(normalizedName);
|
|
830
839
|
}
|
|
831
840
|
if (matches.length > 1) {
|
|
832
841
|
throw new Error(`Multiple extension RPC request handlers registered: ${normalizedName}`);
|
|
@@ -971,6 +980,15 @@ export class ExtensionRunner {
|
|
|
971
980
|
runner.assertActive();
|
|
972
981
|
return runner.getCompactionSettingsFn();
|
|
973
982
|
},
|
|
983
|
+
get getCompactionModel() {
|
|
984
|
+
runner.assertActive();
|
|
985
|
+
return runner.getCompactionModelFn
|
|
986
|
+
? () => {
|
|
987
|
+
runner.assertActive();
|
|
988
|
+
return runner.getCompactionModelFn?.();
|
|
989
|
+
}
|
|
990
|
+
: undefined;
|
|
991
|
+
},
|
|
974
992
|
getPromptCacheSafeWaitSeconds: () => {
|
|
975
993
|
runner.assertActive();
|
|
976
994
|
return runner.getPromptCacheSafeWaitSecondsFn();
|
|
@@ -983,6 +1001,22 @@ export class ExtensionRunner {
|
|
|
983
1001
|
runner.assertActive();
|
|
984
1002
|
return runner.getPromptCacheKeepAliveSettingsFn();
|
|
985
1003
|
},
|
|
1004
|
+
onUserActivity: (listener) => {
|
|
1005
|
+
runner.assertActive();
|
|
1006
|
+
const unsubscribe = runner.onUserActivityFn?.((kind) => {
|
|
1007
|
+
try {
|
|
1008
|
+
listener(kind);
|
|
1009
|
+
}
|
|
1010
|
+
catch (error) {
|
|
1011
|
+
runner.emitError({
|
|
1012
|
+
extensionPath: excludeBeforeProviderRequestExtensionPath ?? RUNTIME_EXTENSION_PATH,
|
|
1013
|
+
event: "user_activity",
|
|
1014
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
});
|
|
1018
|
+
return runner.runtime.trackEventBusSubscription(unsubscribe ?? (() => { }));
|
|
1019
|
+
},
|
|
986
1020
|
getLookAtSettings: () => {
|
|
987
1021
|
runner.assertActive();
|
|
988
1022
|
return runner.getLookAtSettingsFn();
|
|
@@ -1003,9 +1037,9 @@ export class ExtensionRunner {
|
|
|
1003
1037
|
runner.assertActive();
|
|
1004
1038
|
runner.compactFn(options);
|
|
1005
1039
|
},
|
|
1006
|
-
prepareProviderRequest: async (messages) => {
|
|
1040
|
+
prepareProviderRequest: async (messages, options) => {
|
|
1007
1041
|
runner.assertActive();
|
|
1008
|
-
return runner.prepareProviderRequest(messages, excludeBeforeProviderRequestExtensionPath);
|
|
1042
|
+
return runner.prepareProviderRequest(messages, excludeBeforeProviderRequestExtensionPath, options);
|
|
1009
1043
|
},
|
|
1010
1044
|
getPromptCachePrefixRequest: async (options) => {
|
|
1011
1045
|
runner.assertActive();
|
|
@@ -1133,9 +1167,24 @@ export class ExtensionRunner {
|
|
|
1133
1167
|
const ctx = this.createContext();
|
|
1134
1168
|
let entries = [];
|
|
1135
1169
|
let shouldContinue = false;
|
|
1136
|
-
|
|
1137
|
-
let
|
|
1170
|
+
// Reported only when the runner retires before its first preview build completes.
|
|
1171
|
+
let context = {
|
|
1172
|
+
contextEntries: [],
|
|
1173
|
+
contextMessages: [],
|
|
1174
|
+
llmMessages: [],
|
|
1175
|
+
pendingMessages: [],
|
|
1176
|
+
canContinue: false,
|
|
1177
|
+
};
|
|
1138
1178
|
const retired = () => ({ entries: [], continue: false, context, valid: false });
|
|
1179
|
+
try {
|
|
1180
|
+
context = await buildContext(entries);
|
|
1181
|
+
}
|
|
1182
|
+
catch (err) {
|
|
1183
|
+
if (!this.isActive)
|
|
1184
|
+
return retired();
|
|
1185
|
+
throw err;
|
|
1186
|
+
}
|
|
1187
|
+
let valid = true;
|
|
1139
1188
|
for (const { ext, handlers } of snapshotEventHandlers(this.extensions, baseEvent.type)) {
|
|
1140
1189
|
for (const handler of handlers) {
|
|
1141
1190
|
if (!this.isActive)
|
|
@@ -1546,11 +1595,11 @@ export class ExtensionRunner {
|
|
|
1546
1595
|
source,
|
|
1547
1596
|
});
|
|
1548
1597
|
}
|
|
1549
|
-
async prepareProviderRequest(messages, excludeExtensionPath) {
|
|
1598
|
+
async prepareProviderRequest(messages, excludeExtensionPath, options) {
|
|
1550
1599
|
const transformedMessages = await this.emitContext(messages, excludeExtensionPath, "projection");
|
|
1551
1600
|
return {
|
|
1552
1601
|
messages: transformedMessages,
|
|
1553
|
-
transformPayload: async (payload) => await this.emitBeforeProviderRequest(payload, excludeExtensionPath),
|
|
1602
|
+
transformPayload: async (payload) => await this.emitBeforeProviderRequest(options?.allowServerSearch ? payload : disableServerSearch(payload), excludeExtensionPath),
|
|
1554
1603
|
transformHeaders: async (headers) => await this.emitBeforeProviderHeaders(headers),
|
|
1555
1604
|
};
|
|
1556
1605
|
}
|
|
@@ -40,6 +40,7 @@ import type { McpServerDeclaration } from "./builtin/mcp/config-schema.ts";
|
|
|
40
40
|
import type { EvalHandleHost } from "./eval-handle-host.ts";
|
|
41
41
|
import type { ExtensionKernelTools } from "./kernel-tools-context.ts";
|
|
42
42
|
import type { SessionControlActions, SessionControlWakeEvent } from "./session-control-types.ts";
|
|
43
|
+
import type { UserActivityKind } from "./user-activity.ts";
|
|
43
44
|
export type { ExecOptions, ExecResult } from "../exec.ts";
|
|
44
45
|
export type { AppKeybinding, KeybindingsManager } from "../keybindings.ts";
|
|
45
46
|
export type { BuildSystemPromptOptions, NormalizedBuildSystemPromptOptions } from "../system-prompt.ts";
|
|
@@ -432,6 +433,8 @@ export interface ExtensionContext {
|
|
|
432
433
|
getContextUsage(): ContextUsage | undefined;
|
|
433
434
|
/** Get resolved compaction settings from global/project/user overrides. */
|
|
434
435
|
getCompactionSettings(): CompactionPreparation["settings"];
|
|
436
|
+
/** Session-selected usable summarization model; throws when every authenticated account is spent. */
|
|
437
|
+
getCompactionModel?(): Model<Api> | undefined;
|
|
435
438
|
/**
|
|
436
439
|
* Longest a tool may block in the foreground before the active model's prompt
|
|
437
440
|
* cache expires, or `undefined` when no cache-derived budget applies. Reads the
|
|
@@ -440,6 +443,8 @@ export interface ExtensionContext {
|
|
|
440
443
|
getPromptCacheSafeWaitSeconds?(): number | undefined;
|
|
441
444
|
/** Maximum Goal monitor continuation backstop configured for prompt-cache waits. */
|
|
442
445
|
getPromptCacheGoalBackstopMaxSeconds?(): number;
|
|
446
|
+
/** Subscribe to host-authenticated activity; extensions cannot publish it. */
|
|
447
|
+
onUserActivity?(listener: (kind: UserActivityKind) => void): () => void;
|
|
443
448
|
/** Resolved opt-in prompt-cache keep-alive policy. */
|
|
444
449
|
getPromptCacheKeepAliveSettings?(): {
|
|
445
450
|
enabled: boolean;
|
|
@@ -468,9 +473,12 @@ export interface ExtensionContext {
|
|
|
468
473
|
compact(options?: CompactOptions): void;
|
|
469
474
|
/**
|
|
470
475
|
* Prepare a request-local provider context through the normal extension
|
|
471
|
-
* boundary. Persisted session messages are never modified.
|
|
476
|
+
* boundary. Persisted session messages are never modified. Server search is
|
|
477
|
+
* disabled for these auxiliary requests unless preserving a keepalive prefix.
|
|
472
478
|
*/
|
|
473
|
-
prepareProviderRequest?(messages: AgentMessage[]
|
|
479
|
+
prepareProviderRequest?(messages: AgentMessage[], options?: {
|
|
480
|
+
allowServerSearch?: boolean;
|
|
481
|
+
}): Promise<ProviderRequestPreparation>;
|
|
474
482
|
/**
|
|
475
483
|
* The provider request prefix the next user turn will send, with an empty conversation:
|
|
476
484
|
* the system prompt composed through a `before_agent_start` preview pass, the session's
|
|
@@ -2379,8 +2387,10 @@ export interface ExtensionContextActions {
|
|
|
2379
2387
|
shutdown: () => void;
|
|
2380
2388
|
getContextUsage: () => ContextUsage | undefined;
|
|
2381
2389
|
getCompactionSettings: () => CompactionPreparation["settings"];
|
|
2390
|
+
getCompactionModel?: () => Model<Api> | undefined;
|
|
2382
2391
|
getPromptCacheSafeWaitSeconds?: () => number | undefined;
|
|
2383
2392
|
getPromptCacheGoalBackstopMaxSeconds?: () => number;
|
|
2393
|
+
onUserActivity?: (listener: (kind: UserActivityKind) => void) => () => void;
|
|
2384
2394
|
getPromptCacheKeepAliveSettings?: () => {
|
|
2385
2395
|
enabled: boolean;
|
|
2386
2396
|
maxRequestsPerSession: number;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type UserActivityKind = "draft" | "prompt";
|
|
2
|
+
/** Only the owning AgentSession receives the emitter; extensions can only subscribe. */
|
|
3
|
+
export declare function createUserActivitySource(): {
|
|
4
|
+
emit(kind: UserActivityKind): void;
|
|
5
|
+
subscribe(listener: (kind: UserActivityKind) => void): () => void;
|
|
6
|
+
};
|
|
7
|
+
export declare function emitUserActivity(session: {
|
|
8
|
+
recordUserActivity?(kind: UserActivityKind): void;
|
|
9
|
+
} | undefined, kind: UserActivityKind): void;
|
|
10
|
+
//# sourceMappingURL=user-activity.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Only the owning AgentSession receives the emitter; extensions can only subscribe. */
|
|
2
|
+
export function createUserActivitySource() {
|
|
3
|
+
const listeners = new Set();
|
|
4
|
+
return {
|
|
5
|
+
emit(kind) {
|
|
6
|
+
for (const listener of listeners)
|
|
7
|
+
listener(kind);
|
|
8
|
+
},
|
|
9
|
+
subscribe(listener) {
|
|
10
|
+
listeners.add(listener);
|
|
11
|
+
return () => {
|
|
12
|
+
listeners.delete(listener);
|
|
13
|
+
};
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function emitUserActivity(session, kind) {
|
|
18
|
+
session?.recordUserActivity?.(kind);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=user-activity.js.map
|