@herbertgao/pi-extensions 2026.9.11 → 2026.9.13
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/README.md +4 -4
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +1 -1
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +8 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +1 -1
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +5 -4
- package/node_modules/@herbertgao/pi-subagents/src/mention-clone.ts +39 -16
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@narumitw/pi-btw/README.md +21 -4
- package/node_modules/@narumitw/pi-btw/dist/index.ts +1668 -958
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +4 -4
- package/node_modules/@narumitw/pi-btw/docs/workflows.md +10 -2
- package/node_modules/@narumitw/pi-btw/package.json +1 -1
- package/node_modules/@narumitw/pi-btw/src/btw.ts +17 -79
- package/node_modules/@narumitw/pi-btw/src/conversation-context.ts +74 -0
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +196 -7
- package/node_modules/@narumitw/pi-btw/src/main-thread-updates.ts +40 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -2
- package/node_modules/@narumitw/pi-btw/src/settings.ts +49 -0
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +9 -1
- package/node_modules/@narumitw/pi-btw/src/workspace-layout.ts +559 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +62 -0
- package/node_modules/pi-mcp-adapter/README.md +75 -7
- package/node_modules/pi-mcp-adapter/bearer-command-resolver.ts +193 -0
- package/node_modules/pi-mcp-adapter/cli.js +56 -5
- package/node_modules/pi-mcp-adapter/commands.ts +96 -5
- package/node_modules/pi-mcp-adapter/config.ts +73 -6
- package/node_modules/pi-mcp-adapter/direct-tool-surface.ts +22 -28
- package/node_modules/pi-mcp-adapter/direct-tools.ts +13 -5
- package/node_modules/pi-mcp-adapter/dist/abort.d.ts +2 -0
- package/node_modules/pi-mcp-adapter/dist/abort.js +36 -0
- package/node_modules/pi-mcp-adapter/dist/abort.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.d.ts +6 -0
- package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.js +194 -0
- package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/config.d.ts +5 -0
- package/node_modules/pi-mcp-adapter/dist/config.js +75 -6
- package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/consent-manager.d.ts +18 -0
- package/node_modules/pi-mcp-adapter/dist/consent-manager.js +88 -0
- package/node_modules/pi-mcp-adapter/dist/consent-manager.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/elicitation-handler.d.ts +17 -0
- package/node_modules/pi-mcp-adapter/dist/elicitation-handler.js +316 -0
- package/node_modules/pi-mcp-adapter/dist/elicitation-handler.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/errors.d.ts +131 -0
- package/node_modules/pi-mcp-adapter/dist/errors.js +278 -0
- package/node_modules/pi-mcp-adapter/dist/errors.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/http-ca.d.ts +8 -0
- package/node_modules/pi-mcp-adapter/dist/http-ca.js +88 -0
- package/node_modules/pi-mcp-adapter/dist/http-ca.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/jev-client.d.ts +15 -0
- package/node_modules/pi-mcp-adapter/dist/jev-client.js +340 -0
- package/node_modules/pi-mcp-adapter/dist/jev-client.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/jev-contracts.d.ts +77 -0
- package/node_modules/pi-mcp-adapter/dist/jev-contracts.js +2 -0
- package/node_modules/pi-mcp-adapter/dist/jev-contracts.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/jev-key-store.d.ts +22 -0
- package/node_modules/pi-mcp-adapter/dist/jev-key-store.js +85 -0
- package/node_modules/pi-mcp-adapter/dist/jev-key-store.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/json-schema-validator.d.ts +2 -0
- package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js +55 -0
- package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/lifecycle.d.ts +56 -0
- package/node_modules/pi-mcp-adapter/dist/lifecycle.js +410 -0
- package/node_modules/pi-mcp-adapter/dist/lifecycle.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/logger.d.ts +51 -0
- package/node_modules/pi-mcp-adapter/dist/logger.js +131 -0
- package/node_modules/pi-mcp-adapter/dist/logger.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.d.ts +26 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.js +103 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.d.ts +118 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.js +1098 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-auth.d.ts +168 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-auth.js +1117 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-auth.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.js +7 -140
- package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.d.ts +53 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.js +441 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.d.ts +148 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.js +689 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-probe.d.ts +6 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-probe.js +166 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-probe.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-tasks.d.ts +102 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-tasks.js +369 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-tasks.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-trace.d.ts +95 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-trace.js +242 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-trace.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +2 -11
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/npx-resolver.d.ts +6 -0
- package/node_modules/pi-mcp-adapter/dist/npx-resolver.js +505 -0
- package/node_modules/pi-mcp-adapter/dist/npx-resolver.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/request-headers-command.d.ts +10 -0
- package/node_modules/pi-mcp-adapter/dist/request-headers-command.js +312 -0
- package/node_modules/pi-mcp-adapter/dist/request-headers-command.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/runtime-owner.d.ts +13 -0
- package/node_modules/pi-mcp-adapter/dist/runtime-owner.js +97 -0
- package/node_modules/pi-mcp-adapter/dist/runtime-owner.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/sampling-handler.d.ts +17 -0
- package/node_modules/pi-mcp-adapter/dist/sampling-handler.js +203 -0
- package/node_modules/pi-mcp-adapter/dist/sampling-handler.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/secure-keyring.d.ts +11 -0
- package/node_modules/pi-mcp-adapter/dist/secure-keyring.js +172 -0
- package/node_modules/pi-mcp-adapter/dist/secure-keyring.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/server-manager.d.ts +157 -0
- package/node_modules/pi-mcp-adapter/dist/server-manager.js +1743 -0
- package/node_modules/pi-mcp-adapter/dist/server-manager.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/session-approvals.d.ts +34 -0
- package/node_modules/pi-mcp-adapter/dist/session-approvals.js +140 -0
- package/node_modules/pi-mcp-adapter/dist/session-approvals.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/session-recovery.d.ts +26 -0
- package/node_modules/pi-mcp-adapter/dist/session-recovery.js +142 -0
- package/node_modules/pi-mcp-adapter/dist/session-recovery.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/state.d.ts +73 -0
- package/node_modules/pi-mcp-adapter/dist/state.js +2 -0
- package/node_modules/pi-mcp-adapter/dist/state.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/types.d.ts +36 -0
- package/node_modules/pi-mcp-adapter/dist/types.js +18 -0
- package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.d.ts +17 -0
- package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.js +219 -0
- package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.d.ts +15 -0
- package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.js +85 -0
- package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/utils.d.ts +1 -0
- package/node_modules/pi-mcp-adapter/dist/utils.js +13 -0
- package/node_modules/pi-mcp-adapter/dist/utils.js.map +1 -1
- package/node_modules/pi-mcp-adapter/elicitation-handler.ts +29 -19
- package/node_modules/pi-mcp-adapter/examples/jev-accessibility-loop.mjs +85 -0
- package/node_modules/pi-mcp-adapter/examples/jev-semantic-filter.mjs +34 -0
- package/node_modules/pi-mcp-adapter/index.ts +129 -6
- package/node_modules/pi-mcp-adapter/init.ts +6 -19
- package/node_modules/pi-mcp-adapter/jev-client.ts +273 -0
- package/node_modules/pi-mcp-adapter/jev-contracts.ts +53 -0
- package/node_modules/pi-mcp-adapter/jev-key-store.ts +79 -0
- package/node_modules/pi-mcp-adapter/lifecycle.ts +14 -3
- package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +7 -142
- package/node_modules/pi-mcp-adapter/mcp-code.ts +119 -11
- package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +4 -0
- package/node_modules/pi-mcp-adapter/mcp-references.ts +5 -3
- package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +5 -0
- package/node_modules/pi-mcp-adapter/mcp-tasks.ts +467 -0
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +2 -13
- package/node_modules/pi-mcp-adapter/namespace-tools.ts +1 -1
- package/node_modules/pi-mcp-adapter/package.json +17 -9
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +319 -166
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +6 -3
- package/node_modules/pi-mcp-adapter/search-ranking.ts +38 -7
- package/node_modules/pi-mcp-adapter/secure-keyring.ts +170 -0
- package/node_modules/pi-mcp-adapter/semantic-search.ts +186 -0
- package/node_modules/pi-mcp-adapter/server-manager.ts +293 -50
- package/node_modules/pi-mcp-adapter/session-approvals.ts +14 -0
- package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +2 -0
- package/node_modules/pi-mcp-adapter/state.ts +3 -1
- package/node_modules/pi-mcp-adapter/tool-approval.ts +26 -4
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +6 -14
- package/node_modules/pi-mcp-adapter/tool-registrar.ts +8 -6
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +4 -1
- package/node_modules/pi-mcp-adapter/types.ts +53 -0
- package/node_modules/pi-mcp-adapter/ui-server.ts +17 -9
- package/node_modules/pi-mcp-adapter/utils.ts +16 -0
- package/node_modules/pi-multi-account/CHANGELOG.md +23 -0
- package/node_modules/pi-multi-account/README.md +38 -11
- package/node_modules/pi-multi-account/index.ts +371 -96
- package/node_modules/pi-multi-account/package.json +5 -4
- package/node_modules/pi-multi-account/provider-payload-stream.ts +36 -28
- package/node_modules/pi-multi-account/usage.ts +31 -2
- package/node_modules/pi-typesafe/README.md +3 -1
- package/node_modules/pi-typesafe/dist/auth.d.ts +10 -3
- package/node_modules/pi-typesafe/dist/auth.js +13 -7
- package/node_modules/pi-typesafe/dist/backends.d.ts +31 -0
- package/node_modules/pi-typesafe/dist/backends.js +33 -0
- package/node_modules/pi-typesafe/dist/client.d.ts +3 -9
- package/node_modules/pi-typesafe/dist/client.js +63 -39
- package/node_modules/pi-typesafe/dist/credentials.d.ts +11 -5
- package/node_modules/pi-typesafe/dist/credentials.js +15 -8
- package/node_modules/pi-typesafe/dist/extension.js +4 -1
- package/node_modules/pi-typesafe/dist/index.d.ts +1 -1
- package/node_modules/pi-typesafe/dist/index.js +1 -1
- package/node_modules/pi-typesafe/dist/login.d.ts +13 -7
- package/node_modules/pi-typesafe/dist/login.js +17 -8
- package/node_modules/pi-typesafe/dist/schema.js +19 -13
- package/node_modules/pi-typesafe/package.json +1 -1
- package/package.json +11 -10
|
@@ -3,9 +3,12 @@ import { formatWithOptions } from "node:util";
|
|
|
3
3
|
import { Worker } from "node:worker_threads";
|
|
4
4
|
import { throwIfAborted } from "./abort.ts";
|
|
5
5
|
import { guardMcpOutput, guardedMcpDetails, resolveMcpOutputGuardOptions } from "./mcp-output-guard.ts";
|
|
6
|
+
import { evaluateJev, validateJevSettings } from "./jev-client.ts";
|
|
7
|
+
import type { JevErrorCode, JevEvaluateInput, JevEvaluationEnvelope } from "./jev-contracts.ts";
|
|
6
8
|
import { executeCall } from "./proxy-modes.ts";
|
|
7
9
|
import { combineAbortSignals } from "./runtime-owner.ts";
|
|
8
10
|
import { paginate, rankSuggestions, rankToolMatches } from "./search-ranking.ts";
|
|
11
|
+
import { semanticSearch, type SemanticSearchEvaluator } from "./semantic-search.ts";
|
|
9
12
|
import { isServerInActiveFailureBackoff } from "./failure-backoff.ts";
|
|
10
13
|
import type { McpExtensionState } from "./state.ts";
|
|
11
14
|
import { findToolByName, formatSchema, hasSchemaDescriptions } from "./tool-metadata.ts";
|
|
@@ -22,11 +25,12 @@ class McpScriptTimeoutError extends Error {
|
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
type SearchInput = { query?: unknown; server?: unknown; limit?: unknown; offset?: unknown };
|
|
28
|
+
type SearchInput = { query?: unknown; server?: unknown; limit?: unknown; offset?: unknown; searchMode?: unknown; regex?: unknown };
|
|
26
29
|
type DescribeInput = { path?: unknown };
|
|
27
30
|
type WorkerMessage =
|
|
28
31
|
| { type: "emit"; block: unknown }
|
|
29
32
|
| { type: "call"; id: number; path: string; args?: unknown }
|
|
33
|
+
| { type: "evaluate"; id: number; input: unknown }
|
|
30
34
|
| { type: "search"; id: number; input?: unknown }
|
|
31
35
|
| { type: "describe"; id: number; input?: unknown }
|
|
32
36
|
| { type: "done"; returnBlock?: unknown }
|
|
@@ -94,6 +98,9 @@ function parseWorkerMessage(value: unknown): WorkerMessage | null {
|
|
|
94
98
|
? { type: "call", id: message.id, path: message.path, args: message.args }
|
|
95
99
|
: { type: "call", id: message.id, path: message.path };
|
|
96
100
|
}
|
|
101
|
+
if (message.type === "evaluate" && typeof message.id === "number" && "input" in message) {
|
|
102
|
+
return { type: "evaluate", id: message.id, input: message.input };
|
|
103
|
+
}
|
|
97
104
|
if ((message.type === "search" || message.type === "describe") && typeof message.id === "number") {
|
|
98
105
|
return "input" in message
|
|
99
106
|
? { type: message.type, id: message.id, input: message.input }
|
|
@@ -108,12 +115,20 @@ function parseWorkerMessage(value: unknown): WorkerMessage | null {
|
|
|
108
115
|
return null;
|
|
109
116
|
}
|
|
110
117
|
|
|
118
|
+
export type McpScriptJevEvaluator = (
|
|
119
|
+
state: McpExtensionState,
|
|
120
|
+
input: JevEvaluateInput,
|
|
121
|
+
options: { purpose: "script"; signal?: AbortSignal; observedSources?: readonly string[] },
|
|
122
|
+
) => Promise<JevEvaluationEnvelope>;
|
|
123
|
+
|
|
111
124
|
export async function runMcpScript(
|
|
112
125
|
state: McpExtensionState,
|
|
113
126
|
code: string,
|
|
114
127
|
timeoutMs = DEFAULT_MCP_SCRIPT_TIMEOUT_MS,
|
|
115
128
|
getPiTools?: () => ToolInfo[],
|
|
116
129
|
signal?: AbortSignal,
|
|
130
|
+
jevEvaluator: McpScriptJevEvaluator = evaluateJev,
|
|
131
|
+
semanticEvaluator?: SemanticSearchEvaluator,
|
|
117
132
|
) {
|
|
118
133
|
const resolvedTimeoutMs = Number.isFinite(timeoutMs) && timeoutMs > 0
|
|
119
134
|
? Math.floor(timeoutMs)
|
|
@@ -122,6 +137,7 @@ export async function runMcpScript(
|
|
|
122
137
|
const externalSignal = combineAbortSignals(state.owner?.signal, signal);
|
|
123
138
|
const timeoutController = new AbortController();
|
|
124
139
|
const callSignal = combineAbortSignals(externalSignal, timeoutController.signal);
|
|
140
|
+
const observedSources = new Set<string>();
|
|
125
141
|
|
|
126
142
|
type ScriptOperation =
|
|
127
143
|
| { operation: "call"; path: string; ok: true; durationMs: number }
|
|
@@ -129,7 +145,9 @@ export async function runMcpScript(
|
|
|
129
145
|
| { operation: "search"; query: string; ok: true; durationMs: number }
|
|
130
146
|
| { operation: "search"; query: string; ok: false; error: string; durationMs: number }
|
|
131
147
|
| { operation: "describe"; path: string; ok: true; durationMs: number }
|
|
132
|
-
| { operation: "describe"; path: string; ok: false; error: string; durationMs: number }
|
|
148
|
+
| { operation: "describe"; path: string; ok: false; error: string; durationMs: number }
|
|
149
|
+
| { operation: "evaluate"; ok: true; model: string; inputTokens: number; outputTokens: number; durationMs: number }
|
|
150
|
+
| { operation: "evaluate"; ok: false; error: JevErrorCode | "incomplete"; durationMs: number };
|
|
133
151
|
type TrackedScriptOperation = ScriptOperation & { startedAt: number };
|
|
134
152
|
const calls: TrackedScriptOperation[] = [];
|
|
135
153
|
const snapshotCalls = (): ScriptOperation[] => calls.map(({ startedAt, ...operation }) => ({
|
|
@@ -140,6 +158,12 @@ export async function runMcpScript(
|
|
|
140
158
|
}));
|
|
141
159
|
let callsSnapshot: ScriptOperation[] | undefined;
|
|
142
160
|
let intermediateBytes = 0;
|
|
161
|
+
const reserveIntermediateBytes = (dataJson: string): boolean => {
|
|
162
|
+
const bytes = Buffer.byteLength(dataJson, "utf8");
|
|
163
|
+
if (bytes > MCP_SCRIPT_INTERMEDIATE_MAX_BYTES - intermediateBytes) return false;
|
|
164
|
+
intermediateBytes += bytes;
|
|
165
|
+
return true;
|
|
166
|
+
};
|
|
143
167
|
const callTool = async (path: string, args?: Record<string, unknown>): Promise<WorkerResultPayload> => {
|
|
144
168
|
// Record before dispatch so calls still in flight at timeout/abort appear in the trace.
|
|
145
169
|
const startedAt = Date.now();
|
|
@@ -152,6 +176,7 @@ export async function runMcpScript(
|
|
|
152
176
|
},
|
|
153
177
|
});
|
|
154
178
|
const details = result.details;
|
|
179
|
+
if (typeof details.server === "string") observedSources.add(details.server);
|
|
155
180
|
if (details.error !== undefined) {
|
|
156
181
|
const errorCode = String(details.error);
|
|
157
182
|
const suggestions = Array.isArray(details.suggestions)
|
|
@@ -169,8 +194,7 @@ export async function runMcpScript(
|
|
|
169
194
|
}
|
|
170
195
|
throwIfAborted(callSignal);
|
|
171
196
|
if (dataJson === undefined) throw new Error("MCP intermediate result was not JSON serializable");
|
|
172
|
-
|
|
173
|
-
if (bytes > MCP_SCRIPT_INTERMEDIATE_MAX_BYTES - intermediateBytes) {
|
|
197
|
+
if (!reserveIntermediateBytes(dataJson)) {
|
|
174
198
|
const code = "intermediate_result_too_large";
|
|
175
199
|
calls[index] = { operation: "call", path, ok: false, error: code, durationMs: Date.now() - startedAt, startedAt };
|
|
176
200
|
return {
|
|
@@ -181,23 +205,104 @@ export async function runMcpScript(
|
|
|
181
205
|
};
|
|
182
206
|
}
|
|
183
207
|
// Rejected responses do not consume budget. This bounds transfer, not upstream allocation.
|
|
184
|
-
intermediateBytes += bytes;
|
|
185
208
|
calls[index] = { operation: "call", path, ok: true, durationMs: Date.now() - startedAt, startedAt };
|
|
186
209
|
return { dataJson };
|
|
187
210
|
};
|
|
188
211
|
|
|
189
|
-
const
|
|
212
|
+
const jevSettings = validateJevSettings(state.config.settings?.jev);
|
|
213
|
+
let evaluationAttempts = 0;
|
|
214
|
+
let evaluationBytes = 0;
|
|
215
|
+
let evaluationTokensRemaining = jevSettings.maxEvaluationTokensPerScript;
|
|
216
|
+
const tokenBudgetExhausted = (): JevEvaluationEnvelope => ({ ok: false, error: { code: "budget_exhausted", message: "TypeSafe evaluation token budget exhausted." } });
|
|
217
|
+
const chargeEvaluationTokens = (envelope: JevEvaluationEnvelope): JevEvaluationEnvelope => {
|
|
218
|
+
if (!envelope.ok) return envelope;
|
|
219
|
+
const used = envelope.data.usage.inputTokens + envelope.data.usage.outputTokens;
|
|
220
|
+
if (!Number.isSafeInteger(used) || used < 0 || used > evaluationTokensRemaining) {
|
|
221
|
+
evaluationTokensRemaining = 0;
|
|
222
|
+
return tokenBudgetExhausted();
|
|
223
|
+
}
|
|
224
|
+
evaluationTokensRemaining -= used;
|
|
225
|
+
return envelope;
|
|
226
|
+
};
|
|
227
|
+
const admitEvaluation = (input: unknown): JevEvaluationEnvelope | undefined => {
|
|
228
|
+
if (++evaluationAttempts > jevSettings.maxEvaluationsPerScript) {
|
|
229
|
+
return { ok: false, error: { code: "budget_exhausted", message: "TypeSafe evaluation count budget exhausted." } };
|
|
230
|
+
}
|
|
231
|
+
if (evaluationTokensRemaining === 0) return tokenBudgetExhausted();
|
|
232
|
+
let serialized: string | undefined;
|
|
233
|
+
try { serialized = JSON.stringify(input); }
|
|
234
|
+
catch { return { ok: false, error: { code: "invalid_request", message: "Invalid TypeSafe evaluation request." } }; }
|
|
235
|
+
if (serialized === undefined) return { ok: false, error: { code: "invalid_request", message: "Invalid TypeSafe evaluation request." } };
|
|
236
|
+
const bytes = Buffer.byteLength(serialized, "utf8");
|
|
237
|
+
if (bytes > jevSettings.maxEvaluationBytesPerScript - evaluationBytes) {
|
|
238
|
+
return { ok: false, error: { code: "budget_exhausted", message: "TypeSafe evaluation byte budget exhausted." } };
|
|
239
|
+
}
|
|
240
|
+
evaluationBytes += bytes;
|
|
241
|
+
return undefined;
|
|
242
|
+
};
|
|
243
|
+
const evaluate = async (input: unknown): Promise<WorkerResultPayload> => {
|
|
244
|
+
const startedAt = Date.now();
|
|
245
|
+
const index = calls.push({ operation: "evaluate", ok: false, error: "incomplete", durationMs: 0, startedAt }) - 1;
|
|
246
|
+
let envelope: JevEvaluationEnvelope;
|
|
247
|
+
const rejected = admitEvaluation(input);
|
|
248
|
+
if (rejected) {
|
|
249
|
+
envelope = rejected;
|
|
250
|
+
} else {
|
|
251
|
+
envelope = await jevEvaluator(state, input as JevEvaluateInput, {
|
|
252
|
+
purpose: "script",
|
|
253
|
+
...(callSignal ? { signal: callSignal } : {}),
|
|
254
|
+
...(observedSources.size > 0 ? { observedSources: [...observedSources] } : {}),
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
envelope = chargeEvaluationTokens(envelope);
|
|
258
|
+
throwIfAborted(callSignal);
|
|
259
|
+
if (!reserveIntermediateBytes(JSON.stringify(envelope))) {
|
|
260
|
+
envelope = { ok: false, error: { code: "budget_exhausted", message: "TypeSafe evaluation exceeds the remaining mcpScript intermediate transfer budget (16 MiB per script)." } };
|
|
261
|
+
}
|
|
262
|
+
calls[index] = envelope.ok
|
|
263
|
+
? {
|
|
264
|
+
operation: "evaluate", ok: true, model: envelope.data.model,
|
|
265
|
+
inputTokens: envelope.data.usage.inputTokens, outputTokens: envelope.data.usage.outputTokens,
|
|
266
|
+
durationMs: Date.now() - startedAt, startedAt,
|
|
267
|
+
}
|
|
268
|
+
: { operation: "evaluate", ok: false, error: envelope.error.code, durationMs: Date.now() - startedAt, startedAt };
|
|
269
|
+
return { envelope };
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const searchTools = async (input?: SearchInput) => {
|
|
190
273
|
const startedAt = Date.now();
|
|
191
274
|
const query = typeof input?.query === "string" ? input.query : "";
|
|
275
|
+
const index = calls.push({ operation: "search", query, ok: false, error: "incomplete", durationMs: 0, startedAt }) - 1;
|
|
192
276
|
let error: unknown;
|
|
193
277
|
try {
|
|
194
|
-
if (
|
|
278
|
+
if (input?.searchMode !== undefined && input.searchMode !== "lexical" && input.searchMode !== "semantic") {
|
|
279
|
+
error = "invalid_search_mode";
|
|
280
|
+
return { items: [], total: 0, hasMore: false, nextOffset: null, error: { code: "invalid_search_mode", message: "Search mode must be lexical or semantic." } };
|
|
281
|
+
}
|
|
282
|
+
if (query.trim() === "" && input?.searchMode !== "semantic") {
|
|
195
283
|
return { items: [], total: 0, hasMore: false, nextOffset: null };
|
|
196
284
|
}
|
|
197
285
|
const server = typeof input?.server === "string" ? input.server : undefined;
|
|
198
286
|
const limit = typeof input?.limit === "number" ? input.limit : 12;
|
|
199
287
|
const offset = typeof input?.offset === "number" ? input.offset : 0;
|
|
200
|
-
const
|
|
288
|
+
const searchMode = input?.searchMode === "semantic" ? "semantic" : "lexical";
|
|
289
|
+
if (searchMode === "semantic" && input?.regex === true) {
|
|
290
|
+
error = "invalid_search_mode";
|
|
291
|
+
return { items: [], total: 0, hasMore: false, nextOffset: null, error: { code: "invalid_search_mode", message: "Semantic search cannot be combined with regex search." } };
|
|
292
|
+
}
|
|
293
|
+
const semantic = searchMode === "semantic"
|
|
294
|
+
? await semanticSearch(state, query, server, callSignal, async (semanticState, semanticInput, options) => {
|
|
295
|
+
const rejected = admitEvaluation(semanticInput);
|
|
296
|
+
if (rejected) return rejected;
|
|
297
|
+
const envelope = await (semanticEvaluator ?? evaluateJev)(semanticState, semanticInput, options);
|
|
298
|
+
return chargeEvaluationTokens(envelope);
|
|
299
|
+
}, [...observedSources])
|
|
300
|
+
: undefined;
|
|
301
|
+
if (semantic && !semantic.ok) {
|
|
302
|
+
error = semantic.error.code;
|
|
303
|
+
return { items: [], total: 0, hasMore: false, nextOffset: null, error: semantic.error };
|
|
304
|
+
}
|
|
305
|
+
const page = paginate(semantic?.matches ?? rankToolMatches(state, query, server), offset, limit);
|
|
201
306
|
return {
|
|
202
307
|
...page,
|
|
203
308
|
items: page.items.map(({ server: matchServer, tool, score }) => ({
|
|
@@ -207,14 +312,15 @@ export async function runMcpScript(
|
|
|
207
312
|
...(tool.description ? { description: tool.description } : {}),
|
|
208
313
|
score,
|
|
209
314
|
})),
|
|
315
|
+
...(semantic ? { backend: semantic.backend } : {}),
|
|
210
316
|
};
|
|
211
317
|
} catch (caught) {
|
|
212
318
|
error = caught;
|
|
213
319
|
throw caught;
|
|
214
320
|
} finally {
|
|
215
|
-
calls
|
|
321
|
+
calls[index] = error === undefined
|
|
216
322
|
? { operation: "search", query, ok: true, durationMs: Date.now() - startedAt, startedAt }
|
|
217
|
-
: { operation: "search", query, ok: false, error: error instanceof Error ? error.message : String(error), durationMs: Date.now() - startedAt, startedAt }
|
|
323
|
+
: { operation: "search", query, ok: false, error: error instanceof Error ? error.message : String(error), durationMs: Date.now() - startedAt, startedAt };
|
|
218
324
|
}
|
|
219
325
|
};
|
|
220
326
|
|
|
@@ -308,8 +414,10 @@ export async function runMcpScript(
|
|
|
308
414
|
let payload: WorkerResultPayload;
|
|
309
415
|
if (message.type === "call") {
|
|
310
416
|
payload = await callTool(message.path, message.args as Record<string, unknown> | undefined);
|
|
417
|
+
} else if (message.type === "evaluate") {
|
|
418
|
+
payload = await evaluate(message.input);
|
|
311
419
|
} else if (message.type === "search") {
|
|
312
|
-
payload = { envelope: searchTools(message.input as SearchInput | undefined) };
|
|
420
|
+
payload = { envelope: await searchTools(message.input as SearchInput | undefined) };
|
|
313
421
|
} else {
|
|
314
422
|
payload = { envelope: describeTool(message.input as DescribeInput | undefined) };
|
|
315
423
|
}
|
|
@@ -404,12 +404,16 @@ function summarizeStructuredContent(value: unknown): Record<string, unknown> {
|
|
|
404
404
|
fields[key] = candidate;
|
|
405
405
|
preservedBytes += entryBytes;
|
|
406
406
|
}
|
|
407
|
+
const preservedCount = Object.keys(fields).length;
|
|
407
408
|
return {
|
|
409
|
+
omitted: true,
|
|
408
410
|
preservedFields: fields,
|
|
409
411
|
summary: {
|
|
410
412
|
type: "object",
|
|
411
413
|
estimatedBytes: estimateValueBytes(value),
|
|
412
414
|
keyCount: keys.length,
|
|
415
|
+
preservedCount,
|
|
416
|
+
droppedCount: keys.length - preservedCount,
|
|
413
417
|
keysPreview: previewKeys,
|
|
414
418
|
omitted: true,
|
|
415
419
|
},
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
isServerDisabled,
|
|
8
8
|
isToolAllowed,
|
|
9
9
|
resolveToolPrefix,
|
|
10
|
+
resolveUniqueNameOwnership,
|
|
10
11
|
type CachedTool,
|
|
11
12
|
type McpConfig,
|
|
12
13
|
type ServerCacheEntry,
|
|
@@ -97,6 +98,7 @@ function hasNamespaceProxy(
|
|
|
97
98
|
existingDirectNames: ReadonlySet<string>,
|
|
98
99
|
serverName: string,
|
|
99
100
|
): boolean {
|
|
101
|
+
if (config.settings?.namespaceProxyTools === false) return false;
|
|
100
102
|
const definition = config.mcpServers[serverName];
|
|
101
103
|
if (!definition || isServerDisabled(definition)) return false;
|
|
102
104
|
if (isMcpServerDirectlyRegistered(definition, config.settings, serverName, envOverride)) return false;
|
|
@@ -146,14 +148,14 @@ function registeredDirectNames(
|
|
|
146
148
|
envOverride: DirectToolSelectorOverride | null,
|
|
147
149
|
selectorIndex: ToolSelectorCandidateIndex | undefined,
|
|
148
150
|
): Map<string, DirectNameOwner> {
|
|
149
|
-
const
|
|
151
|
+
const entries: Array<{ name: string; owner: DirectNameOwner }> = [];
|
|
150
152
|
for (const { serverName, definition, entry, prefix } of cachedServers(config, cache)) {
|
|
151
153
|
const selection = resolveDirectSelection(config, definition, serverName, envOverride);
|
|
152
154
|
for (const { name, originalName } of directNameEntries(entry, serverName, definition, prefix, selection, selectorIndex)) {
|
|
153
|
-
|
|
155
|
+
entries.push({ name, owner: { serverName, originalName } });
|
|
154
156
|
}
|
|
155
157
|
}
|
|
156
|
-
return
|
|
158
|
+
return new Map(resolveUniqueNameOwnership(entries, (entry) => entry.name).unique.map(({ name, owner }) => [name, owner]));
|
|
157
159
|
}
|
|
158
160
|
|
|
159
161
|
function allCurrentCandidates(config: McpConfig, cache: MetadataCache | null): ToolSelectorCandidateIndex | undefined {
|
|
@@ -96,6 +96,10 @@ const tools = new Proxy(Object.create(null), {
|
|
|
96
96
|
},
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
+
const jev = Object.freeze({
|
|
100
|
+
evaluate: (input) => request("evaluate", { input }),
|
|
101
|
+
});
|
|
102
|
+
|
|
99
103
|
const emit = (value) => {
|
|
100
104
|
parentPort.postMessage({ type: "emit", block: toContentBlock(value) });
|
|
101
105
|
};
|
|
@@ -112,6 +116,7 @@ void (async () => {
|
|
|
112
116
|
try {
|
|
113
117
|
const context = vm.createContext(Object.assign(Object.create(null), {
|
|
114
118
|
tools,
|
|
119
|
+
jev,
|
|
115
120
|
emit,
|
|
116
121
|
console: capturedConsole,
|
|
117
122
|
}), {
|