@narumitw/pi-chrome-devtools 0.53.2 → 0.53.3
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 +1 -0
- package/dist/chunks/{browser-settings-menu-IMB6HXSU.js → browser-settings-menu-SR7KLZT6.js} +16 -42
- package/dist/chunks/browser-settings-menu-SR7KLZT6.js.map +7 -0
- package/dist/chunks/{chunk-GTTYS5GT.js → chunk-4KMN4SFF.js} +2 -2
- package/dist/chunks/chunk-4KMN4SFF.js.map +7 -0
- package/dist/chunks/{chunk-SRT3UUIP.js → chunk-F5VG35UI.js} +23 -74
- package/dist/chunks/chunk-F5VG35UI.js.map +7 -0
- package/dist/chunks/{chunk-LLXOCRNF.js → chunk-MZCGM6D3.js} +12 -33
- package/dist/chunks/chunk-MZCGM6D3.js.map +7 -0
- package/dist/chunks/{menu-UJETYMSB.js → menu-YR4VRT7D.js} +10 -23
- package/dist/chunks/menu-YR4VRT7D.js.map +7 -0
- package/dist/chunks/{tools-6P7EUX37.js → tools-6R7Z6HWJ.js} +17 -59
- package/dist/chunks/tools-6R7Z6HWJ.js.map +7 -0
- package/dist/index.ts +18 -42
- package/dist/index.ts.map +2 -2
- package/package.json +54 -55
- package/src/browser-manager.ts +872 -942
- package/src/browser-settings-menu.ts +315 -350
- package/src/cdp-client.ts +381 -398
- package/src/chrome-devtools.ts +205 -232
- package/src/display.ts +26 -29
- package/src/lazy-tools.ts +158 -181
- package/src/menu.ts +409 -446
- package/src/render.ts +72 -81
- package/src/runtime.ts +137 -140
- package/src/screenshot.ts +170 -186
- package/src/settings.ts +472 -523
- package/src/tool-names.ts +8 -14
- package/src/tool-selector.ts +242 -271
- package/src/tools.ts +218 -226
- package/src/webmcp/discovery.ts +184 -188
- package/src/webmcp/policy.ts +296 -329
- package/src/webmcp/protocol.ts +324 -337
- package/src/webmcp/tools.ts +136 -147
- package/dist/chunks/browser-settings-menu-IMB6HXSU.js.map +0 -7
- package/dist/chunks/chunk-GTTYS5GT.js.map +0 -7
- package/dist/chunks/chunk-LLXOCRNF.js.map +0 -7
- package/dist/chunks/chunk-SRT3UUIP.js.map +0 -7
- package/dist/chunks/menu-UJETYMSB.js.map +0 -7
- package/dist/chunks/tools-6P7EUX37.js.map +0 -7
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/menu.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ExtensionAPI, ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport { defineMenu, runMenu, runTask } from \"@narumitw/pi-tui-kit\";\nimport { browserLifecycleState, devToolsEndpoint, launchAttemptLines, launchModeLabel } from \"./browser-manager.js\";\nimport { availableChromeDevtoolsTools } from \"./lazy-tools.js\";\nimport { state, webMcpEnabled } from \"./runtime.js\";\nimport { loadSettings, type SettingsLoadResult } from \"./settings.js\";\nimport {\n CHROME_DEVTOOLS_TOOL_NAMES,\n type ChromeDevToolsToolName,\n CORE_CHROME_DEVTOOLS_TOOL_NAMES,\n} from \"./tool-names.js\";\nimport {\n buildBrowserStatusMessage,\n buildCommandGuide,\n sanitizeChromeDevtoolsDisplay,\n setSelectedChromeDevtoolsTools,\n} from \"./tool-selector.js\";\n\ntype CommandContext = ExtensionCommandContext;\ntype MainScreen = \"main\" | \"browserStatus\" | \"help\";\ntype MainAction = \"tools\" | \"bulk\" | \"settings\";\ntype ToolScreen = \"tools\" | \"review\";\ntype ToolAction = \"toggle\" | \"selectAll\" | \"selectNone\" | \"review\" | \"apply\" | \"cancel\";\n\ninterface MenuSnapshot {\n activeTools: ChromeDevToolsToolName[];\n persistenceLabel: string;\n mutationBlockedReason?: string;\n settingsWarning?: string;\n}\n\ninterface ToolWorkflowState {\n accepted: Set<ChromeDevToolsToolName>;\n draft: Set<ChromeDevToolsToolName>;\n mutationBlockedReason?: string;\n generation: number;\n applied: boolean;\n}\n\nconst TOOL_PRESENTATION: Record<ChromeDevToolsToolName, { label: string; description: string }> = {\n chrome_devtools_list_pages: {\n label: \"List open pages\",\n description: \"List inspectable Chrome tabs and pages (chrome_devtools_list_pages).\",\n },\n chrome_devtools_select_page: {\n label: \"Select the active page\",\n description: \"Choose the page later browser actions use (chrome_devtools_select_page).\",\n },\n chrome_devtools_navigate: {\n label: \"Navigate a page\",\n description: \"Open a URL, creating a page when needed (chrome_devtools_navigate).\",\n },\n chrome_devtools_evaluate: {\n label: \"Run JavaScript\",\n description: \"Evaluate JavaScript in the selected page (chrome_devtools_evaluate).\",\n },\n chrome_devtools_screenshot: {\n label: \"Capture a screenshot\",\n description: \"Save a PNG of the selected page (chrome_devtools_screenshot).\",\n },\n chrome_devtools_webmcp_list_tools: {\n label: \"List page WebMCP tools \u00B7 Experimental\",\n description: \"Discover page-provided WebMCP capabilities (chrome_devtools_webmcp_list_tools).\",\n },\n chrome_devtools_webmcp_call_tool: {\n label: \"Call a page WebMCP tool \u00B7 Experimental\",\n description: \"Invoke a listed page tool after confirmation (chrome_devtools_webmcp_call_tool).\",\n },\n};\n\nexport async function showChromeDevtoolsMenu(pi: ExtensionAPI, ctx: CommandContext, generation: number) {\n const snapshot = await loadSnapshotWithFeedback(pi, ctx, generation);\n if (!snapshot) return;\n const menuSignal = state.sessionController.signal;\n const isCurrent = () => generation === state.sessionGeneration && !menuSignal.aborted;\n const menu = defineMenu<MenuSnapshot, MainScreen, MainAction>({\n start: \"main\",\n screens: {\n main: ({ state: current }) => ({\n kind: \"actions\",\n title: \"Chrome DevTools\",\n lines: mainStateLines(current, ctx.sessionManager),\n items: [\n {\n id: \"tools\",\n label: \"Choose available browser tools\u2026\",\n description: \"Choose which capabilities the loader may expose.\",\n disabled: Boolean(current.mutationBlockedReason),\n disabledReason: current.mutationBlockedReason,\n action: \"tools\",\n },\n {\n id: \"bulk\",\n label:\n current.activeTools.length === availableCatalogNames(ctx.sessionManager).length\n ? \"Make all browser tools unavailable\u2026\"\n : \"Make all browser tools available\u2026\",\n description:\n current.activeTools.length === availableCatalogNames(ctx.sessionManager).length\n ? `Preview 0 of ${availableCatalogNames(ctx.sessionManager).length}; other active tools stay enabled.`\n : `Preview ${availableCatalogNames(ctx.sessionManager).length} of ${availableCatalogNames(ctx.sessionManager).length}; other active tools stay enabled.`,\n disabled: Boolean(current.mutationBlockedReason),\n disabledReason: current.mutationBlockedReason,\n action: \"bulk\",\n },\n {\n id: \"browser-status\",\n label: \"Browser status\",\n description: \"Runtime, endpoint, and last launch attempt.\",\n to: \"browserStatus\",\n },\n {\n id: \"settings\",\n label: \"Browser settings\",\n description: \"Edit endpoint, auto-launch, and browser executable settings.\",\n action: \"settings\",\n },\n {\n id: \"help\",\n label: \"Help\",\n description: \"Commands and usage.\",\n to: \"help\",\n },\n ],\n hint: \"close\",\n }),\n browserStatus: () => ({\n kind: \"review\",\n title: \"Browser status\",\n content: buildBrowserStatusMessage(ctx.sessionManager),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n help: () => ({\n kind: \"review\",\n title: \"Chrome DevTools help\",\n content: buildCommandGuide(ctx.sessionManager),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n },\n actions: {\n tools: async ({ state: current }) => {\n const result = await showChromeDevtoolsToolWorkflow(pi, ctx, generation, {\n snapshot: current,\n });\n if (result?.applied && isCurrent()) updateSnapshotAfterApply(current, result.selectedTools);\n return result?.closeParent ? { kind: \"close\" } : { kind: \"stay\" };\n },\n bulk: async ({ state: current }) => {\n const selectedTools =\n current.activeTools.length === availableCatalogNames(ctx.sessionManager).length\n ? []\n : availableCatalogNames(ctx.sessionManager);\n const result = await showChromeDevtoolsToolWorkflow(pi, ctx, generation, {\n snapshot: current,\n initialDraft: selectedTools,\n startAtReview: true,\n });\n if (result?.applied && isCurrent()) updateSnapshotAfterApply(current, result.selectedTools);\n return result?.closeParent ? { kind: \"close\" } : { kind: \"stay\" };\n },\n settings: async ({ state: current }) => {\n const { showChromeDevtoolsBrowserSettings } = await import(\"./browser-settings-menu.js\");\n if (!isCurrent()) return { kind: \"stay\" };\n const result = await showChromeDevtoolsBrowserSettings(pi, ctx, generation);\n if (!isCurrent()) return { kind: \"stay\" };\n const refreshed = await loadChromeDevtoolsMenuSnapshot(pi, ctx);\n if (!isCurrent()) return { kind: \"stay\" };\n Object.assign(current, refreshed);\n return result.closeParent ? { kind: \"close\" } : { kind: \"stay\" };\n },\n },\n });\n await runMenu(ctx, menu, {\n getState: () => snapshot,\n signal: menuSignal,\n isCurrent,\n onError: (currentCtx, error) =>\n currentCtx.ui.notify(\n sanitizeChromeDevtoolsDisplay(`Chrome DevTools menu failed: ${formatError(error)}`),\n \"error\",\n ),\n });\n}\n\nexport async function showChromeDevtoolsToolWorkflow(\n pi: ExtensionAPI,\n ctx: CommandContext,\n generation: number,\n options: {\n snapshot?: MenuSnapshot;\n initialDraft?: readonly ChromeDevToolsToolName[];\n startAtReview?: boolean;\n } = {},\n): Promise<{ applied: boolean; closeParent: boolean; selectedTools: ChromeDevToolsToolName[] } | undefined> {\n const snapshot = options.snapshot ?? (await loadSnapshotWithFeedback(pi, ctx, generation));\n if (!snapshot) return undefined;\n const menuSignal = state.sessionController.signal;\n const isCurrent = () => generation === state.sessionGeneration && !menuSignal.aborted;\n const accepted = new Set(snapshot.activeTools);\n const workflow: ToolWorkflowState = {\n accepted,\n draft: new Set(options.initialDraft ?? snapshot.activeTools),\n mutationBlockedReason: snapshot.mutationBlockedReason,\n generation,\n applied: false,\n };\n const menu = defineMenu<ToolWorkflowState, ToolScreen, ToolAction>({\n start: options.startAtReview ? \"review\" : \"tools\",\n screens: {\n tools: ({ state: current }) => ({\n kind: \"multiSelect\",\n title: `Browser tools (${current.draft.size}/${availableCatalogNames(ctx.sessionManager).length})`,\n lines: toolDraftLines(current, ctx.sessionManager),\n items: availableCatalogNames(ctx.sessionManager).map((toolName) => ({\n id: toolName,\n label: TOOL_PRESENTATION[toolName].label,\n description: TOOL_PRESENTATION[toolName].description,\n searchText: `${toolName} ${TOOL_PRESENTATION[toolName].description}`,\n selected: current.draft.has(toolName),\n disabled: Boolean(current.mutationBlockedReason),\n disabledReason: current.mutationBlockedReason,\n })),\n action: \"toggle\",\n actions: [\n {\n id: \"select-all\",\n label: \"Select all\",\n disabled: Boolean(current.mutationBlockedReason),\n disabledReason: current.mutationBlockedReason,\n action: \"selectAll\",\n },\n {\n id: \"select-none\",\n label: \"Select none\",\n disabled: Boolean(current.mutationBlockedReason),\n disabledReason: current.mutationBlockedReason,\n action: \"selectNone\",\n },\n {\n id: \"review\",\n label: \"Review changes\u2026\",\n disabled: Boolean(current.mutationBlockedReason) || setsEqual(current.accepted, current.draft),\n disabledReason:\n current.mutationBlockedReason ??\n (setsEqual(current.accepted, current.draft) ? \"No unapplied changes\" : undefined),\n to: \"review\",\n },\n { id: \"cancel\", label: \"Cancel\", action: \"cancel\" },\n ],\n hint: \"back\",\n }),\n review: ({ state: current }) => ({\n kind: \"review\",\n title: \"Review tool changes\",\n lines: [\n `Currently available: ${current.accepted.size}/${availableCatalogNames(ctx.sessionManager).length}`,\n `Proposed availability: ${current.draft.size}/${availableCatalogNames(ctx.sessionManager).length}`,\n ],\n content: buildToolReview(current, ctx.sessionManager),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n ...(current.mutationBlockedReason || setsEqual(current.accepted, current.draft)\n ? {}\n : {\n confirm: {\n id: \"apply\",\n label: \"Apply tool changes\",\n action: \"apply\" as const,\n },\n }),\n hint: \"back\",\n }),\n },\n actions: {\n toggle: ({ state: current, itemId, selected }) => {\n if (!isChromeDevtoolsToolName(itemId) || selected === undefined) return { kind: \"rejected\" };\n if (selected) current.draft.add(itemId);\n else current.draft.delete(itemId);\n return { kind: \"stay\" };\n },\n selectAll: ({ state: current }) => {\n current.draft = new Set(availableCatalogNames(ctx.sessionManager));\n return { kind: \"stay\" };\n },\n selectNone: ({ state: current }) => {\n current.draft = new Set();\n return { kind: \"stay\" };\n },\n review: () => ({ kind: \"to\", screen: \"review\" }),\n cancel: () => ({ kind: \"back\" }),\n apply: async ({ state: current, signal }) => {\n await ctx.waitForIdle();\n if (signal.aborted || !isCurrent() || current.generation !== state.sessionGeneration) {\n return { kind: \"rejected\" };\n }\n const selectedTools = orderedTools(current.draft);\n const saveResult = await setSelectedChromeDevtoolsTools(pi, ctx, selectedTools, orderedTools(current.accepted));\n if (!isCurrent()) return { kind: \"rejected\" };\n if (saveResult === \"active-tools-changed\") {\n current.accepted = new Set(activeChromeTools(pi));\n }\n if (saveResult !== \"saved\") return { kind: \"rejected\" };\n current.accepted = new Set(selectedTools);\n current.draft = new Set(selectedTools);\n current.applied = true;\n ctx.ui.notify(\n `Saved: ${selectedTools.length} of ${availableCatalogNames(ctx.sessionManager).length} browser tools available.`,\n \"info\",\n );\n return { kind: \"close\" };\n },\n },\n });\n const result = await runMenu(ctx, menu, {\n getState: () => workflow,\n signal: menuSignal,\n isCurrent,\n onError: (currentCtx, error) =>\n currentCtx.ui.notify(\n sanitizeChromeDevtoolsDisplay(`Chrome DevTools tool selection failed: ${formatError(error)}`),\n \"error\",\n ),\n });\n return {\n applied: workflow.applied,\n closeParent: !workflow.applied && result.kind === \"closed\" && result.reason === \"close\",\n selectedTools: orderedTools(workflow.accepted),\n };\n}\n\nasync function loadSnapshotWithFeedback(pi: ExtensionAPI, ctx: CommandContext, generation: number) {\n const menuSignal = state.sessionController.signal;\n const isCurrent = () => generation === state.sessionGeneration && !menuSignal.aborted;\n const result = await runTask(ctx, {\n label: \"Loading Chrome DevTools settings\u2026\",\n signal: menuSignal,\n isCurrent,\n task: async ({ signal }) => {\n signal.throwIfAborted();\n const settings = await loadSettings();\n signal.throwIfAborted();\n return buildMenuSnapshot(pi, settings);\n },\n });\n return result.kind === \"completed\" ? result.value : undefined;\n}\n\nexport async function loadChromeDevtoolsMenuSnapshot(pi: ExtensionAPI, ctx: ExtensionCommandContext) {\n const settings = await loadSettings({\n cwd: ctx.cwd,\n projectTrusted: ctx.isProjectTrusted(),\n });\n return buildMenuSnapshot(pi, settings);\n}\n\nfunction buildMenuSnapshot(pi: ExtensionAPI, settings: SettingsLoadResult): MenuSnapshot {\n const activeTools = activeChromeTools(pi);\n const persistedTools =\n settings.kind === \"loaded\" && settings.settings.tools ? orderedTools(new Set(settings.settings.tools)) : undefined;\n const persistenceLabel =\n settings.kind === \"invalid\"\n ? \"settings need repair\"\n : persistedTools === undefined\n ? \"not saved\"\n : arraysEqual(activeTools, persistedTools)\n ? \"saved\"\n : \"runtime catalog differs from saved catalog\";\n const settingsWarning = [...new Set([settings.notice, state.settingsNotice].filter(Boolean))].join(\"\\n\");\n return {\n activeTools,\n persistenceLabel,\n ...(settings.kind === \"invalid\" ? { mutationBlockedReason: `Repair ${settings.reason} before saving` } : {}),\n ...(settingsWarning ? { settingsWarning } : {}),\n };\n}\n\nfunction mainStateLines(snapshot: MenuSnapshot, owner: object) {\n const launchError = launchAttemptLines(owner).find((line) => line.startsWith(\"Last launch error:\"));\n return sanitizeLines([\n `Tool catalog: ${snapshot.activeTools.length} of ${availableCatalogNames(owner).length} available \u00B7 ${snapshot.persistenceLabel}`,\n `WebMCP: ${webMcpEnabled(owner) ? \"enabled \u00B7 experimental \u00B7 confirmation required for every call\" : \"disabled \u00B7 experimental\"}`,\n `Browser: ${browserLifecycleSummary(owner)}`,\n `Endpoint: ${devToolsEndpoint(owner)}`,\n ...(snapshot.settingsWarning ? [`Settings warning: ${snapshot.settingsWarning}`] : []),\n ...(launchError ? [`Launch warning: ${launchError.slice(\"Last launch error: \".length)}`] : []),\n ]);\n}\n\nfunction browserLifecycleSummary(owner: object) {\n const lifecycle = browserLifecycleState(owner);\n if (lifecycle === \"starting\") return \"starting managed browser\";\n if (lifecycle === \"running\") return \"managed browser running\";\n if (lifecycle === \"exited\") return \"managed browser exited \u00B7 open Browser status to recover\";\n if (lifecycle === \"failed\") return \"last launch failed \u00B7 open Browser status to recover\";\n const launchMode = launchModeLabel(owner);\n return launchMode.startsWith(\"attach first\")\n ? \"not started \u00B7 attaches or launches on first use\"\n : `not started \u00B7 ${launchMode}`;\n}\n\nfunction toolDraftLines(current: ToolWorkflowState, owner: object) {\n if (current.mutationBlockedReason) return sanitizeLines([`Unavailable: ${current.mutationBlockedReason}`]);\n const changes = symmetricDifferenceSize(current.accepted, current.draft);\n return [\n `Currently available: ${current.accepted.size}/${availableCatalogNames(owner).length}`,\n changes === 0\n ? \"No unapplied changes \u00B7 Escape cancels\"\n : `${changes} unapplied ${changes === 1 ? \"change\" : \"changes\"} \u00B7 Escape cancels`,\n `WebMCP gateways: ${webMcpEnabled(owner) ? \"available for selection \u00B7 experimental\" : \"hidden while experimental WebMCP is disabled\"}`,\n \"Changes are not applied until Review changes and Apply tool changes.\",\n ];\n}\n\nfunction buildToolReview(current: ToolWorkflowState, owner: object) {\n const catalog = availableCatalogNames(owner);\n const available = catalog.filter((name) => current.draft.has(name));\n const unavailable = catalog.filter((name) => !current.draft.has(name));\n return sanitizeChromeDevtoolsDisplay(\n [\n `Current available browser tools: ${current.accepted.size}/${catalog.length}`,\n `Proposed available browser tools: ${current.draft.size}/${catalog.length}`,\n \"\",\n \"Available after apply:\",\n ...(available.length > 0\n ? available.map((name) => ` - ${TOOL_PRESENTATION[name].label} (${name})`)\n : [\" - none\"]),\n \"\",\n \"Unavailable after apply:\",\n ...(unavailable.length > 0\n ? unavailable.map((name) => ` - ${TOOL_PRESENTATION[name].label} (${name})`)\n : [\" - none\"]),\n \"\",\n \"Other active Pi tools remain unchanged.\",\n \"Native-capable models defer these tools until chrome_devtools_load selects them.\",\n \"Other models expose available tools eagerly before the next model request.\",\n \"The accepted availability policy is saved for future sessions.\",\n ].join(\"\\n\"),\n );\n}\n\nfunction updateSnapshotAfterApply(snapshot: MenuSnapshot, selectedTools: readonly ChromeDevToolsToolName[]) {\n snapshot.activeTools = [...selectedTools];\n snapshot.persistenceLabel = \"saved\";\n}\n\nfunction activeChromeTools(pi: ExtensionAPI) {\n return availableChromeDevtoolsTools(pi);\n}\n\nfunction orderedTools(tools: ReadonlySet<ChromeDevToolsToolName>) {\n return CHROME_DEVTOOLS_TOOL_NAMES.filter((toolName) => tools.has(toolName));\n}\n\nfunction isChromeDevtoolsToolName(value: string): value is ChromeDevToolsToolName {\n return CHROME_DEVTOOLS_TOOL_NAMES.includes(value as ChromeDevToolsToolName);\n}\n\nfunction setsEqual<T>(left: ReadonlySet<T>, right: ReadonlySet<T>) {\n return left.size === right.size && [...left].every((value) => right.has(value));\n}\n\nfunction symmetricDifferenceSize<T>(left: ReadonlySet<T>, right: ReadonlySet<T>) {\n let changes = 0;\n for (const value of left) if (!right.has(value)) changes += 1;\n for (const value of right) if (!left.has(value)) changes += 1;\n return changes;\n}\n\nfunction arraysEqual<T>(left: readonly T[], right: readonly T[]) {\n return left.length === right.length && left.every((value, index) => value === right[index]);\n}\n\nfunction sanitizeLines(lines: readonly string[]) {\n return sanitizeChromeDevtoolsDisplay(lines.join(\"\\n\")).split(\"\\n\");\n}\n\nfunction availableCatalogNames(owner: object): ChromeDevToolsToolName[] {\n return webMcpEnabled(owner) ? [...CHROME_DEVTOOLS_TOOL_NAMES] : [...CORE_CHROME_DEVTOOLS_TOOL_NAMES];\n}\n\nfunction formatError(error: unknown) {\n return error instanceof Error ? error.message : String(error);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
getPage,
|
|
6
6
|
resolvePage,
|
|
7
7
|
textResult
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-4KMN4SFF.js";
|
|
9
9
|
import {
|
|
10
10
|
DEFAULT_TIMEOUT_MS,
|
|
11
11
|
beginWebMcpOperation,
|
|
@@ -15,17 +15,12 @@ import {
|
|
|
15
15
|
webMcpEnabled,
|
|
16
16
|
webMcpOperationIsCurrent,
|
|
17
17
|
webMcpSessionSignal
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-F5VG35UI.js";
|
|
19
19
|
|
|
20
20
|
// src/webmcp/policy.ts
|
|
21
21
|
import { createHash } from "node:crypto";
|
|
22
22
|
import { stripVTControlCharacters } from "node:util";
|
|
23
|
-
import {
|
|
24
|
-
DEFAULT_MAX_BYTES,
|
|
25
|
-
DEFAULT_MAX_LINES,
|
|
26
|
-
formatSize,
|
|
27
|
-
truncateHead
|
|
28
|
-
} from "@earendil-works/pi-coding-agent";
|
|
23
|
+
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead } from "@earendil-works/pi-coding-agent";
|
|
29
24
|
import { Check } from "typebox/value";
|
|
30
25
|
var MAX_WEBMCP_TOOLS = 100;
|
|
31
26
|
var MAX_SCHEMA_BYTES = 64 * 1024;
|
|
@@ -86,9 +81,7 @@ function webMcpIdentity(tool) {
|
|
|
86
81
|
};
|
|
87
82
|
}
|
|
88
83
|
function requireMatchingWebMcpTool(tools, expected) {
|
|
89
|
-
const candidates = tools.filter(
|
|
90
|
-
(tool) => tool.frameId === expected.frameId && tool.name === expected.name
|
|
91
|
-
);
|
|
84
|
+
const candidates = tools.filter((tool) => tool.frameId === expected.frameId && tool.name === expected.name);
|
|
92
85
|
if (candidates.length === 0) throw new Error("The selected WebMCP tool is no longer available.");
|
|
93
86
|
if (candidates.length > 1) {
|
|
94
87
|
throw new Error("The selected WebMCP tool identity is ambiguous in its frame.");
|
|
@@ -186,10 +179,7 @@ function webMcpConfirmationMessage(tool, input, managedProfile) {
|
|
|
186
179
|
].join("\n");
|
|
187
180
|
}
|
|
188
181
|
function sanitizeWebMcpDisplay(value, maxCharacters = 5e4) {
|
|
189
|
-
const withoutBidi = stripVTControlCharacters(value).replace(
|
|
190
|
-
/[\u202a-\u202e\u2066-\u2069]/gu,
|
|
191
|
-
"\uFFFD"
|
|
192
|
-
);
|
|
182
|
+
const withoutBidi = stripVTControlCharacters(value).replace(/[\u202a-\u202e\u2066-\u2069]/gu, "\uFFFD");
|
|
193
183
|
const sanitized = Array.from(withoutBidi, (character) => {
|
|
194
184
|
const codePoint = character.codePointAt(0) ?? 0;
|
|
195
185
|
const unsafeControl = codePoint >= 0 && codePoint <= 8 || codePoint >= 11 && codePoint <= 31 || codePoint >= 127 && codePoint <= 159;
|
|
@@ -238,13 +228,7 @@ function rejectRegexBearingSchema(schema) {
|
|
|
238
228
|
for (const child of schema[keyword]) rejectRegexBearingSchema(child);
|
|
239
229
|
}
|
|
240
230
|
}
|
|
241
|
-
for (const keyword of [
|
|
242
|
-
"$defs",
|
|
243
|
-
"definitions",
|
|
244
|
-
"dependencies",
|
|
245
|
-
"dependentSchemas",
|
|
246
|
-
"properties"
|
|
247
|
-
]) {
|
|
231
|
+
for (const keyword of ["$defs", "definitions", "dependencies", "dependentSchemas", "properties"]) {
|
|
248
232
|
if (!isRecord(schema[keyword])) continue;
|
|
249
233
|
for (const child of Object.values(schema[keyword])) rejectRegexBearingSchema(child);
|
|
250
234
|
}
|
|
@@ -254,9 +238,7 @@ function rejectExpensiveValidationSchema(schema) {
|
|
|
254
238
|
const countBranches = (count) => {
|
|
255
239
|
branches += count;
|
|
256
240
|
if (branches > MAX_SCHEMA_VALIDATION_BRANCHES) {
|
|
257
|
-
throw new Error(
|
|
258
|
-
`WebMCP input schema exceeds the validation branch limit of ${MAX_SCHEMA_VALIDATION_BRANCHES}.`
|
|
259
|
-
);
|
|
241
|
+
throw new Error(`WebMCP input schema exceeds the validation branch limit of ${MAX_SCHEMA_VALIDATION_BRANCHES}.`);
|
|
260
242
|
}
|
|
261
243
|
};
|
|
262
244
|
const visit = (candidate) => {
|
|
@@ -297,8 +279,7 @@ function canonicalJsonValue(value, limits) {
|
|
|
297
279
|
return candidate;
|
|
298
280
|
}
|
|
299
281
|
if (typeof candidate === "number") {
|
|
300
|
-
if (!Number.isFinite(candidate))
|
|
301
|
-
throw new Error(`${limits.label} contains a non-finite number.`);
|
|
282
|
+
if (!Number.isFinite(candidate)) throw new Error(`${limits.label} contains a non-finite number.`);
|
|
302
283
|
return candidate;
|
|
303
284
|
}
|
|
304
285
|
if (Array.isArray(candidate)) return candidate.map((entry) => visit(entry, depth + 1));
|
|
@@ -313,9 +294,7 @@ function canonicalJsonValue(value, limits) {
|
|
|
313
294
|
const serialized = canonicalStringify(canonical);
|
|
314
295
|
const bytes = Buffer.byteLength(serialized, "utf8");
|
|
315
296
|
if (bytes > limits.maxBytes) {
|
|
316
|
-
throw new Error(
|
|
317
|
-
`${limits.label} exceeds ${formatSize(limits.maxBytes)} (${formatSize(bytes)}).`
|
|
318
|
-
);
|
|
297
|
+
throw new Error(`${limits.label} exceeds ${formatSize(limits.maxBytes)} (${formatSize(bytes)}).`);
|
|
319
298
|
}
|
|
320
299
|
return canonical;
|
|
321
300
|
}
|
|
@@ -340,11 +319,7 @@ var REQUIRED_EVENTS = ["toolsAdded", "toolsRemoved", "toolInvoked", "toolRespond
|
|
|
340
319
|
var IDENTITY_WATCH_TIMEOUT_MS = DEFAULT_TIMEOUT_MS * 4;
|
|
341
320
|
async function requireWebMcpDomain(signal, owner) {
|
|
342
321
|
signal.throwIfAborted();
|
|
343
|
-
const protocol = await fetchDevToolsJson(
|
|
344
|
-
"/json/protocol",
|
|
345
|
-
{ signal },
|
|
346
|
-
owner
|
|
347
|
-
);
|
|
322
|
+
const protocol = await fetchDevToolsJson("/json/protocol", { signal }, owner);
|
|
348
323
|
signal.throwIfAborted();
|
|
349
324
|
const domain = findDomain(protocol.domains, "WebMCP");
|
|
350
325
|
if (!domain || !hasNamedEntries(domain.commands, REQUIRED_COMMANDS) || !hasNamedEntries(domain.events, REQUIRED_EVENTS)) {
|
|
@@ -547,9 +522,7 @@ function findDomain(value, name) {
|
|
|
547
522
|
function hasNamedEntries(value, required) {
|
|
548
523
|
if (!Array.isArray(value)) return false;
|
|
549
524
|
const names = new Set(
|
|
550
|
-
value.flatMap(
|
|
551
|
-
(candidate) => isRecord2(candidate) && typeof candidate.name === "string" ? [candidate.name] : []
|
|
552
|
-
)
|
|
525
|
+
value.flatMap((candidate) => isRecord2(candidate) && typeof candidate.name === "string" ? [candidate.name] : [])
|
|
553
526
|
);
|
|
554
527
|
return required.every((name) => names.has(name));
|
|
555
528
|
}
|
|
@@ -734,9 +707,7 @@ function requireStableInventoryDocuments(tools, before, after) {
|
|
|
734
707
|
const beforeLoader = beforeLoaders.get(frameId);
|
|
735
708
|
const afterLoader = afterLoaders.get(frameId);
|
|
736
709
|
if (!beforeLoader || !afterLoader || beforeLoader !== afterLoader) {
|
|
737
|
-
throw new Error(
|
|
738
|
-
"A WebMCP frame document changed while Chrome was publishing its tool inventory."
|
|
739
|
-
);
|
|
710
|
+
throw new Error("A WebMCP frame document changed while Chrome was publishing its tool inventory.");
|
|
740
711
|
}
|
|
741
712
|
}
|
|
742
713
|
}
|
|
@@ -801,9 +772,7 @@ function frameOrigin(frame) {
|
|
|
801
772
|
try {
|
|
802
773
|
return new URL(frame.url).origin;
|
|
803
774
|
} catch {
|
|
804
|
-
throw new Error(
|
|
805
|
-
`Chrome returned an invalid WebMCP frame URL: ${webMcpErrorMessage(frame.url)}`
|
|
806
|
-
);
|
|
775
|
+
throw new Error(`Chrome returned an invalid WebMCP frame URL: ${webMcpErrorMessage(frame.url)}`);
|
|
807
776
|
}
|
|
808
777
|
}
|
|
809
778
|
function remoteExceptionText(value) {
|
|
@@ -832,10 +801,7 @@ async function executeWebMcpListTool(params, toolSignal, ctx) {
|
|
|
832
801
|
try {
|
|
833
802
|
const tools = await discoverWebMcpTools(page, operation);
|
|
834
803
|
assertCurrent(operation);
|
|
835
|
-
const published = boundedWebMcpDiscovery(
|
|
836
|
-
{ id: page.id, title: page.title, url: page.url },
|
|
837
|
-
tools
|
|
838
|
-
);
|
|
804
|
+
const published = boundedWebMcpDiscovery({ id: page.id, title: page.title, url: page.url }, tools);
|
|
839
805
|
return textResult(published.text, {
|
|
840
806
|
page: { id: page.id, url: page.url },
|
|
841
807
|
toolCount: tools.length,
|
|
@@ -884,12 +850,7 @@ async function executeWebMcpCallTool(params, toolSignal, ctx) {
|
|
|
884
850
|
if (!confirmed) {
|
|
885
851
|
throw new DOMException("WebMCP tool call cancelled by the user.", "AbortError");
|
|
886
852
|
}
|
|
887
|
-
const invocation = await invokeDiscoveredWebMcpTool(
|
|
888
|
-
page,
|
|
889
|
-
expected,
|
|
890
|
-
validatedInput,
|
|
891
|
-
operation
|
|
892
|
-
);
|
|
853
|
+
const invocation = await invokeDiscoveredWebMcpTool(page, expected, validatedInput, operation);
|
|
893
854
|
assertCurrent(operation);
|
|
894
855
|
const published = boundedWebMcpJson({
|
|
895
856
|
status: "completed",
|
|
@@ -923,10 +884,7 @@ function combinedSignal(owner, toolSignal) {
|
|
|
923
884
|
function requireCurrentPreflight(owner, generation) {
|
|
924
885
|
requireWebMcpEnabled(owner);
|
|
925
886
|
if (generation !== currentWebMcpGeneration(owner)) {
|
|
926
|
-
throw new DOMException(
|
|
927
|
-
"The WebMCP operation became stale during page resolution.",
|
|
928
|
-
"AbortError"
|
|
929
|
-
);
|
|
887
|
+
throw new DOMException("The WebMCP operation became stale during page resolution.", "AbortError");
|
|
930
888
|
}
|
|
931
889
|
}
|
|
932
890
|
function expectedIdentity(params) {
|
|
@@ -961,4 +919,4 @@ export {
|
|
|
961
919
|
executeWebMcpCallTool,
|
|
962
920
|
executeWebMcpListTool
|
|
963
921
|
};
|
|
964
|
-
//# sourceMappingURL=tools-
|
|
922
|
+
//# sourceMappingURL=tools-6R7Z6HWJ.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/webmcp/policy.ts", "../../src/webmcp/protocol.ts", "../../src/webmcp/discovery.ts", "../../src/webmcp/tools.ts"],
|
|
4
|
+
"sourcesContent": ["import { createHash } from \"node:crypto\";\nimport { stripVTControlCharacters } from \"node:util\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead } from \"@earendil-works/pi-coding-agent\";\nimport type { TSchema } from \"typebox\";\nimport { Check } from \"typebox/value\";\nimport type { WebMcpProtocolAnnotation, WebMcpProtocolTool } from \"./protocol.js\";\n\nexport const MAX_WEBMCP_TOOLS = 100;\nconst MAX_SCHEMA_BYTES = 64 * 1024;\nconst MAX_INPUT_BYTES = 64 * 1024;\nconst MAX_OUTPUT_BYTES = 1024 * 1024;\nconst MAX_JSON_DEPTH = 32;\nconst MAX_JSON_NODES = 10_000;\nconst MAX_OUTPUT_NODES = 100_000;\nconst MAX_SCHEMA_VALIDATION_BRANCHES = 128;\n\nexport interface WebMcpToolDescriptor {\n annotations: WebMcpProtocolAnnotation;\n description: string;\n documentId: string;\n frameId: string;\n frameOrigin: string;\n inputSchema: Record<string, unknown>;\n name: string;\n pageId: string;\n pageUrl: string;\n schemaDigest: string;\n sessionGeneration: string;\n title?: string;\n}\n\nexport interface WebMcpToolIdentity {\n documentId: string;\n frameId: string;\n frameOrigin: string;\n name: string;\n pageId: string;\n schemaDigest: string;\n sessionGeneration: string;\n}\n\nexport function normalizeWebMcpTool(\n tool: WebMcpProtocolTool,\n context: {\n documentId: string;\n frameOrigin: string;\n pageId: string;\n pageUrl: string;\n sessionGeneration: string;\n },\n): WebMcpToolDescriptor {\n const name = boundedString(tool.name, \"tool name\", 512, { nonEmpty: true });\n const description = boundedString(tool.description, \"tool description\", 16 * 1024);\n const title = tool.title === undefined ? undefined : boundedString(tool.title, \"tool title\", 1_024);\n const documentId = boundedString(context.documentId, \"document loader ID\", 512, {\n nonEmpty: true,\n });\n const frameId = boundedString(tool.frameId, \"frame ID\", 512, { nonEmpty: true });\n const frameOrigin = boundedString(context.frameOrigin, \"frame origin\", 2_048, {\n nonEmpty: true,\n });\n const pageId = boundedString(context.pageId, \"page ID\", 512, { nonEmpty: true });\n const pageUrl = boundedString(context.pageUrl, \"page URL\", 8_192);\n const inputSchema = tool.inputSchema ?? { type: \"object\", additionalProperties: true };\n rejectRegexBearingSchema(inputSchema);\n const canonicalSchema = canonicalJsonObject(inputSchema, {\n label: \"WebMCP input schema\",\n maxBytes: MAX_SCHEMA_BYTES,\n maxDepth: MAX_JSON_DEPTH,\n maxNodes: MAX_JSON_NODES,\n });\n rejectExpensiveValidationSchema(canonicalSchema);\n const annotations = canonicalAnnotations(tool.annotations);\n const schemaDigest = createHash(\"sha256\")\n .update(canonicalStringify({ inputSchema: canonicalSchema, annotations }))\n .digest(\"hex\");\n return {\n annotations,\n description,\n documentId,\n frameId,\n frameOrigin,\n inputSchema: canonicalSchema,\n name,\n pageId,\n pageUrl,\n schemaDigest,\n sessionGeneration: context.sessionGeneration,\n ...(title === undefined ? {} : { title }),\n };\n}\n\nexport function webMcpIdentity(tool: WebMcpToolDescriptor): WebMcpToolIdentity {\n return {\n sessionGeneration: tool.sessionGeneration,\n pageId: tool.pageId,\n documentId: tool.documentId,\n frameId: tool.frameId,\n frameOrigin: tool.frameOrigin,\n name: tool.name,\n schemaDigest: tool.schemaDigest,\n };\n}\n\nexport function requireMatchingWebMcpTool(tools: readonly WebMcpToolDescriptor[], expected: WebMcpToolIdentity) {\n const candidates = tools.filter((tool) => tool.frameId === expected.frameId && tool.name === expected.name);\n if (candidates.length === 0) throw new Error(\"The selected WebMCP tool is no longer available.\");\n if (candidates.length > 1) {\n throw new Error(\"The selected WebMCP tool identity is ambiguous in its frame.\");\n }\n const current = candidates[0];\n if (!current) throw new Error(\"The selected WebMCP tool is no longer available.\");\n const mismatches = (\n [\n [\"session generation\", current.sessionGeneration, expected.sessionGeneration],\n [\"page\", current.pageId, expected.pageId],\n [\"document\", current.documentId, expected.documentId],\n [\"frame\", current.frameId, expected.frameId],\n [\"frame origin\", current.frameOrigin, expected.frameOrigin],\n [\"schema or annotations\", current.schemaDigest, expected.schemaDigest],\n ] as const\n ).flatMap(([label, actual, wanted]) => (actual === wanted ? [] : [label]));\n if (mismatches.length > 0) {\n throw new Error(`The selected WebMCP tool became stale: ${mismatches.join(\", \")} changed.`);\n }\n return current;\n}\n\nexport function normalizeWebMcpInput(input: Record<string, unknown>) {\n return canonicalJsonObject(input, {\n label: \"WebMCP tool input\",\n maxBytes: MAX_INPUT_BYTES,\n maxDepth: MAX_JSON_DEPTH,\n maxNodes: MAX_JSON_NODES,\n });\n}\n\nexport function validateWebMcpInput(schema: Record<string, unknown>, input: Record<string, unknown>) {\n const normalized = normalizeWebMcpInput(input);\n let valid: boolean;\n try {\n valid = Check(schema as TSchema, normalized);\n } catch (error) {\n throw new Error(\n `The page provided a WebMCP input schema that cannot be validated: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n if (!valid) throw new Error(\"WebMCP tool input does not match the current page-provided schema.\");\n return normalized;\n}\n\nexport function normalizeWebMcpOutput(output: unknown) {\n return canonicalJsonValue(output, {\n label: \"WebMCP tool output\",\n maxBytes: MAX_OUTPUT_BYTES,\n maxDepth: MAX_JSON_DEPTH * 2,\n maxNodes: MAX_OUTPUT_NODES,\n });\n}\n\nexport function boundedWebMcpDiscovery(\n page: { id: string; title: string; url: string },\n tools: readonly WebMcpToolDescriptor[],\n) {\n const included: WebMcpToolDescriptor[] = [];\n for (const tool of tools) {\n const candidate = [...included, tool];\n const publication = boundedWebMcpJson({\n page,\n tools: candidate,\n totalToolCount: tools.length,\n truncated: candidate.length < tools.length,\n });\n if (publication.truncated) break;\n included.push(tool);\n }\n const truncated = included.length < tools.length;\n const publication = boundedWebMcpJson({\n page,\n tools: included,\n totalToolCount: tools.length,\n truncated,\n });\n if (publication.truncated) {\n throw new Error(\"WebMCP discovery metadata cannot fit within Pi's output limit.\");\n }\n return { ...publication, included, truncated };\n}\n\nexport function boundedWebMcpJson(value: unknown) {\n const serialized = sanitizeWebMcpDisplay(JSON.stringify(value, null, 2), Number.MAX_SAFE_INTEGER);\n const result = truncateHead(serialized, {\n maxBytes: Math.max(1, DEFAULT_MAX_BYTES - 256),\n maxLines: Math.max(1, DEFAULT_MAX_LINES - 2),\n });\n if (!result.truncated) return { text: result.content, truncated: false };\n const notice = `\\n[WebMCP output truncated: ${result.outputLines}/${result.totalLines} lines, ${formatSize(result.outputBytes)}/${formatSize(result.totalBytes)}.]`;\n return { text: `${result.content}${notice}`, truncated: true };\n}\n\nexport function webMcpConfirmationMessage(\n tool: WebMcpToolDescriptor,\n input: Record<string, unknown>,\n managedProfile: boolean,\n) {\n const inputSummary = sanitizeWebMcpDisplay(JSON.stringify(input, null, 2), 2_000);\n return [\n managedProfile\n ? \"This call uses the isolated browser profile managed by Pi.\"\n : \"Warning: this call uses an attached browser profile that may contain everyday authenticated sessions and sensitive state.\",\n `Page: ${sanitizeWebMcpDisplay(tool.pageUrl, 4_096)}`,\n `Frame origin: ${sanitizeWebMcpDisplay(tool.frameOrigin, 2_048)}`,\n `Tool: ${sanitizeWebMcpDisplay(tool.name, 512)}`,\n \"Page annotations are untrusted and do not bypass this confirmation.\",\n \"Input:\",\n inputSummary,\n ].join(\"\\n\");\n}\n\nexport function sanitizeWebMcpDisplay(value: string, maxCharacters = 50_000) {\n const withoutBidi = stripVTControlCharacters(value).replace(/[\\u202a-\\u202e\\u2066-\\u2069]/gu, \"\uFFFD\");\n const sanitized = Array.from(withoutBidi, (character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n const unsafeControl =\n (codePoint >= 0 && codePoint <= 8) ||\n (codePoint >= 11 && codePoint <= 31) ||\n (codePoint >= 127 && codePoint <= 159);\n return unsafeControl ? \"\uFFFD\" : character;\n }).join(\"\");\n if (sanitized.length <= maxCharacters) return sanitized;\n return `${sanitized.slice(0, Math.max(0, maxCharacters - 1))}\u2026`;\n}\n\nexport function webMcpErrorMessage(error: unknown) {\n return sanitizeWebMcpDisplay(error instanceof Error ? error.message : String(error), 8_192);\n}\n\nfunction canonicalAnnotations(value: WebMcpProtocolAnnotation | undefined) {\n if (!value) return {};\n return Object.fromEntries(\n Object.entries(value)\n .filter((entry): entry is [string, boolean] => typeof entry[1] === \"boolean\")\n .sort(([left], [right]) => left.localeCompare(right)),\n ) as WebMcpProtocolAnnotation;\n}\n\nfunction rejectRegexBearingSchema(schema: unknown): void {\n if (Array.isArray(schema)) {\n for (const child of schema) rejectRegexBearingSchema(child);\n return;\n }\n if (!isRecord(schema)) return;\n if (schema.pattern !== undefined || schema.patternProperties !== undefined) {\n throw new Error(\n \"WebMCP input schemas with pattern or patternProperties are unsupported because page-controlled regular expressions cannot be evaluated safely.\",\n );\n }\n for (const keyword of [\n \"additionalItems\",\n \"additionalProperties\",\n \"contains\",\n \"else\",\n \"if\",\n \"items\",\n \"not\",\n \"propertyNames\",\n \"then\",\n \"unevaluatedItems\",\n \"unevaluatedProperties\",\n ] as const) {\n rejectRegexBearingSchema(schema[keyword]);\n }\n for (const keyword of [\"allOf\", \"anyOf\", \"oneOf\", \"prefixItems\"] as const) {\n if (Array.isArray(schema[keyword])) {\n for (const child of schema[keyword]) rejectRegexBearingSchema(child);\n }\n }\n for (const keyword of [\"$defs\", \"definitions\", \"dependencies\", \"dependentSchemas\", \"properties\"] as const) {\n if (!isRecord(schema[keyword])) continue;\n for (const child of Object.values(schema[keyword])) rejectRegexBearingSchema(child);\n }\n}\n\nfunction rejectExpensiveValidationSchema(schema: unknown) {\n let branches = 0;\n const countBranches = (count: number) => {\n branches += count;\n if (branches > MAX_SCHEMA_VALIDATION_BRANCHES) {\n throw new Error(`WebMCP input schema exceeds the validation branch limit of ${MAX_SCHEMA_VALIDATION_BRANCHES}.`);\n }\n };\n const visit = (candidate: unknown): void => {\n if (Array.isArray(candidate)) {\n for (const child of candidate) visit(child);\n return;\n }\n if (!isRecord(candidate)) return;\n for (const keyword of [\"allOf\", \"anyOf\", \"oneOf\"] as const) {\n const alternatives = candidate[keyword];\n if (Array.isArray(alternatives)) countBranches(alternatives.length);\n }\n for (const keyword of [\"dependencies\", \"dependentSchemas\"] as const) {\n const dependencies = candidate[keyword];\n if (!isRecord(dependencies)) continue;\n countBranches(Object.values(dependencies).filter(isRecord).length);\n }\n for (const child of Object.values(candidate)) visit(child);\n };\n visit(schema);\n}\n\ninterface JsonLimits {\n label: string;\n maxBytes: number;\n maxDepth: number;\n maxNodes: number;\n}\n\nfunction canonicalJsonObject(value: Record<string, unknown>, limits: JsonLimits) {\n const canonical = canonicalJsonValue(value, limits);\n if (!isRecord(canonical)) throw new Error(`${limits.label} must be a JSON object.`);\n return canonical;\n}\n\nfunction canonicalJsonValue(value: unknown, limits: JsonLimits) {\n let nodes = 0;\n const visit = (candidate: unknown, depth: number): unknown => {\n nodes += 1;\n if (nodes > limits.maxNodes) {\n throw new Error(`${limits.label} exceeds the ${limits.maxNodes} value limit.`);\n }\n if (depth > limits.maxDepth) {\n throw new Error(`${limits.label} exceeds the depth limit of ${limits.maxDepth}.`);\n }\n if (candidate === null || typeof candidate === \"string\" || typeof candidate === \"boolean\") {\n return candidate;\n }\n if (typeof candidate === \"number\") {\n if (!Number.isFinite(candidate)) throw new Error(`${limits.label} contains a non-finite number.`);\n return candidate;\n }\n if (Array.isArray(candidate)) return candidate.map((entry) => visit(entry, depth + 1));\n if (isRecord(candidate)) {\n return Object.fromEntries(\n Object.keys(candidate)\n .sort()\n .map((key) => [key, visit(candidate[key], depth + 1)]),\n );\n }\n throw new Error(`${limits.label} contains a value that is not JSON-compatible.`);\n };\n const canonical = visit(value, 0);\n const serialized = canonicalStringify(canonical);\n const bytes = Buffer.byteLength(serialized, \"utf8\");\n if (bytes > limits.maxBytes) {\n throw new Error(`${limits.label} exceeds ${formatSize(limits.maxBytes)} (${formatSize(bytes)}).`);\n }\n return canonical;\n}\n\nfunction canonicalStringify(value: unknown) {\n const serialized = JSON.stringify(value);\n if (serialized === undefined) throw new Error(\"Value is not JSON-compatible.\");\n return serialized;\n}\n\nfunction boundedString(value: string, label: string, maxBytes: number, options: { nonEmpty?: boolean } = {}) {\n if (options.nonEmpty && value.length === 0) throw new Error(`WebMCP ${label} must not be empty.`);\n const bytes = Buffer.byteLength(value, \"utf8\");\n if (bytes > maxBytes) throw new Error(`WebMCP ${label} exceeds ${formatSize(maxBytes)}.`);\n return value;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n", "import { fetchDevToolsJson } from \"../browser-manager.js\";\nimport { CdpClient } from \"../cdp-client.js\";\nimport { DEFAULT_TIMEOUT_MS, type DevToolsPage } from \"../runtime.js\";\n\nexport interface WebMcpProtocolAnnotation {\n autosubmit?: boolean;\n consequential?: boolean;\n readOnly?: boolean;\n untrustedContent?: boolean;\n}\n\nexport interface WebMcpProtocolTool {\n annotations?: WebMcpProtocolAnnotation;\n backendNodeId?: number;\n description: string;\n frameId: string;\n inputSchema?: Record<string, unknown>;\n name: string;\n title?: string;\n}\n\nexport interface WebMcpFrame {\n id: string;\n loaderId: string;\n securityOrigin?: string;\n url: string;\n}\n\nexport interface WebMcpInvocationResponse {\n errorText?: string;\n exception?: unknown;\n invocationId: string;\n output?: unknown;\n status: \"Canceled\" | \"Completed\" | \"Error\";\n}\n\nexport interface WebMcpIdentityWatch {\n dispose(): Promise<void>;\n signal: AbortSignal;\n}\n\ninterface ProtocolDescription {\n domains?: unknown;\n}\n\nconst REQUIRED_COMMANDS = [\"enable\", \"disable\", \"invokeTool\", \"cancelInvocation\"];\nconst REQUIRED_EVENTS = [\"toolsAdded\", \"toolsRemoved\", \"toolInvoked\", \"toolResponded\"];\nconst IDENTITY_WATCH_TIMEOUT_MS = DEFAULT_TIMEOUT_MS * 4;\n\nexport async function requireWebMcpDomain(signal: AbortSignal, owner: object) {\n signal.throwIfAborted();\n const protocol = await fetchDevToolsJson<ProtocolDescription>(\"/json/protocol\", { signal }, owner);\n signal.throwIfAborted();\n const domain = findDomain(protocol.domains, \"WebMCP\");\n if (\n !domain ||\n !hasNamedEntries(domain.commands, REQUIRED_COMMANDS) ||\n !hasNamedEntries(domain.events, REQUIRED_EVENTS)\n ) {\n throw new Error(\n \"This browser does not expose the experimental Chrome DevTools WebMCP domain. Use a compatible Chrome build and enable the website's required Origin Trial or WebMCP testing feature.\",\n );\n }\n}\n\nexport async function connectWebMcpPage(page: DevToolsPage, signal: AbortSignal) {\n if (!page.webSocketDebuggerUrl) throw new Error(`Page has no webSocketDebuggerUrl: ${page.id}`);\n return CdpClient.connect(page.webSocketDebuggerUrl, {\n signal: withDeadline(signal),\n });\n}\n\nexport async function cancelWebMcpInvocation(page: DevToolsPage, invocationId: string) {\n const cleanupSignal = AbortSignal.timeout(1_000);\n const client = await connectWebMcpPage(page, cleanupSignal);\n try {\n await client.send(\"WebMCP.cancelInvocation\", { invocationId }, { signal: cleanupSignal });\n } finally {\n client.close();\n }\n}\n\nexport async function enableWebMcpIdentityTracking(client: CdpClient, signal: AbortSignal) {\n await client.send(\"Page.enable\", {}, { signal, timeoutMs: DEFAULT_TIMEOUT_MS });\n}\n\nexport async function enableWebMcp(client: CdpClient, signal: AbortSignal) {\n const eventController = new AbortController();\n const eventSignal = AbortSignal.any([signal, eventController.signal]);\n const toolsAdded = client\n .waitForEvent(\n \"WebMCP.toolsAdded\",\n (value): value is { tools: WebMcpProtocolTool[] } => {\n const parsed = parseToolsAdded(value);\n if (!parsed) throw new Error(\"Chrome sent a malformed WebMCP.toolsAdded event\");\n return true;\n },\n { signal: eventSignal, timeoutMs: DEFAULT_TIMEOUT_MS },\n )\n .then(\n (value) => ({ ok: true as const, value }),\n (error: unknown) => ({ error, ok: false as const }),\n );\n try {\n await client.send(\"WebMCP.enable\", {}, { signal, timeoutMs: DEFAULT_TIMEOUT_MS });\n } catch (error) {\n eventController.abort();\n await toolsAdded;\n throw error;\n }\n try {\n const result = await toolsAdded;\n if (!result.ok) throw result.error;\n const parsed = parseToolsAdded(result.value);\n if (!parsed) throw new Error(\"Chrome sent a malformed WebMCP.toolsAdded event\");\n return parsed.tools;\n } finally {\n eventController.abort();\n }\n}\n\nexport async function disableWebMcp(client: CdpClient) {\n try {\n await client.send(\"WebMCP.disable\", {}, { timeoutMs: 1_000 });\n } catch {\n // Best-effort cleanup: the target may already be detached or the domain may be unavailable.\n }\n}\n\nexport async function readWebMcpFrames(client: CdpClient, signal: AbortSignal) {\n const result = await client.send<unknown>(\n \"Page.getFrameTree\",\n {},\n {\n signal,\n timeoutMs: DEFAULT_TIMEOUT_MS,\n },\n );\n const frames = parseFrameTree(result);\n if (!frames) throw new Error(\"Chrome sent a malformed Page.getFrameTree response\");\n return frames;\n}\n\nexport function watchWebMcpIdentity(\n client: CdpClient,\n expected: { documentId: string; frameId: string; toolName: string },\n signal: AbortSignal,\n): WebMcpIdentityWatch {\n const stopController = new AbortController();\n const staleController = new AbortController();\n const watchSignal = AbortSignal.any([signal, stopController.signal]);\n const options = { signal: watchSignal, timeoutMs: IDENTITY_WATCH_TIMEOUT_MS };\n const settleWatch = (create: () => Promise<unknown>) => {\n let watch: Promise<unknown>;\n try {\n watch = create();\n } catch (error) {\n watch = Promise.reject(error);\n }\n return watch.then(\n () => {\n if (staleController.signal.aborted) return;\n staleController.abort(\n new DOMException(\n \"The selected WebMCP document or tool changed before Chrome completed the invocation boundary.\",\n \"AbortError\",\n ),\n );\n },\n (error) => {\n if (stopController.signal.aborted || signal.aborted || staleController.signal.aborted) {\n return;\n }\n staleController.abort(error);\n },\n );\n };\n const settledWatches = [\n settleWatch(() =>\n client.waitForEvent(\n \"Page.frameNavigated\",\n (value): value is unknown => frameNavigationChangesIdentity(value, expected.frameId, expected.documentId),\n options,\n ),\n ),\n settleWatch(() =>\n client.waitForEvent(\n \"WebMCP.toolsAdded\",\n (value): value is unknown => toolChangeMatchesIdentity(value, expected),\n options,\n ),\n ),\n settleWatch(() =>\n client.waitForEvent(\n \"WebMCP.toolsRemoved\",\n (value): value is unknown => toolChangeMatchesIdentity(value, expected),\n options,\n ),\n ),\n ];\n return {\n signal: AbortSignal.any([signal, staleController.signal]),\n async dispose() {\n stopController.abort();\n await Promise.allSettled(settledWatches);\n },\n };\n}\n\nexport async function invokeWebMcpTool(\n client: CdpClient,\n request: { frameId: string; input: Record<string, unknown>; toolName: string },\n signal: AbortSignal,\n fallbackCancel?: (invocationId: string) => Promise<unknown>,\n): Promise<WebMcpInvocationResponse> {\n signal.throwIfAborted();\n let invocationId: string | undefined;\n let cancellation: Promise<unknown> | undefined;\n const cancel = () => {\n if (!invocationId || cancellation) return;\n const invocationToCancel = invocationId;\n const recoverCancellation = () =>\n fallbackCancel ? fallbackCancel(invocationToCancel).catch(() => undefined) : Promise.resolve();\n try {\n cancellation = client\n .send(\"WebMCP.cancelInvocation\", { invocationId }, { timeoutMs: 1_000 })\n .catch(recoverCancellation);\n } catch {\n cancellation = recoverCancellation();\n }\n };\n const onAbort = () => cancel();\n signal.addEventListener(\"abort\", onAbort, { once: true });\n try {\n let response: unknown;\n try {\n response = await client.send<unknown>(\n \"WebMCP.invokeTool\",\n { frameId: request.frameId, toolName: request.toolName, input: request.input },\n { timeoutMs: DEFAULT_TIMEOUT_MS },\n );\n } catch (error) {\n if (signal.aborted) throw signal.reason;\n throw error;\n }\n invocationId = parseInvocationId(response);\n if (!invocationId) throw new Error(\"Chrome sent a malformed WebMCP.invokeTool response\");\n if (signal.aborted) cancel();\n let event: WebMcpInvocationResponse;\n try {\n event = await client.waitForEvent(\n \"WebMCP.toolResponded\",\n (value): value is WebMcpInvocationResponse => {\n const parsed = parseToolResponded(value);\n if (!parsed) throw new Error(\"Chrome sent a malformed WebMCP.toolResponded event\");\n return parsed.invocationId === invocationId;\n },\n { timeoutMs: DEFAULT_TIMEOUT_MS },\n );\n } catch (error) {\n cancel();\n await cancellation;\n if (signal.aborted) throw signal.reason;\n throw error;\n }\n if (signal.aborted) throw signal.reason;\n return event;\n } finally {\n signal.removeEventListener(\"abort\", onAbort);\n await cancellation;\n }\n}\n\nfunction findDomain(value: unknown, name: string): Record<string, unknown> | undefined {\n if (!Array.isArray(value)) return undefined;\n return value.find(\n (candidate): candidate is Record<string, unknown> => isRecord(candidate) && candidate.domain === name,\n );\n}\n\nfunction hasNamedEntries(value: unknown, required: readonly string[]) {\n if (!Array.isArray(value)) return false;\n const names = new Set(\n value.flatMap((candidate) => (isRecord(candidate) && typeof candidate.name === \"string\" ? [candidate.name] : [])),\n );\n return required.every((name) => names.has(name));\n}\n\nfunction parseToolsAdded(value: unknown): { tools: WebMcpProtocolTool[] } | undefined {\n if (!isRecord(value) || !Array.isArray(value.tools)) return undefined;\n const tools: WebMcpProtocolTool[] = [];\n for (const candidate of value.tools) {\n const tool = parseTool(candidate);\n if (!tool) return undefined;\n tools.push(tool);\n }\n return { tools };\n}\n\nfunction parseTool(value: unknown): WebMcpProtocolTool | undefined {\n if (\n !isRecord(value) ||\n typeof value.name !== \"string\" ||\n typeof value.description !== \"string\" ||\n typeof value.frameId !== \"string\" ||\n (value.inputSchema !== undefined && !isRecord(value.inputSchema)) ||\n (value.title !== undefined && typeof value.title !== \"string\") ||\n (value.backendNodeId !== undefined && typeof value.backendNodeId !== \"number\")\n ) {\n return undefined;\n }\n const annotations = parseAnnotations(value.annotations);\n if (value.annotations !== undefined && !annotations) return undefined;\n return {\n name: value.name,\n description: value.description,\n frameId: value.frameId,\n ...(value.title === undefined ? {} : { title: value.title }),\n ...(value.inputSchema === undefined ? {} : { inputSchema: value.inputSchema }),\n ...(annotations ? { annotations } : {}),\n ...(value.backendNodeId === undefined ? {} : { backendNodeId: value.backendNodeId }),\n };\n}\n\nfunction parseAnnotations(value: unknown): WebMcpProtocolAnnotation | undefined {\n if (value === undefined) return undefined;\n if (!isRecord(value)) return undefined;\n const annotations: WebMcpProtocolAnnotation = {};\n for (const key of [\"autosubmit\", \"consequential\", \"readOnly\", \"untrustedContent\"] as const) {\n if (value[key] === undefined) continue;\n if (typeof value[key] !== \"boolean\") return undefined;\n annotations[key] = value[key];\n }\n return annotations;\n}\n\nfunction parseFrameTree(value: unknown): WebMcpFrame[] | undefined {\n if (!isRecord(value) || !isRecord(value.frameTree)) return undefined;\n const frames: WebMcpFrame[] = [];\n const visit = (tree: unknown): boolean => {\n if (!isRecord(tree) || !isRecord(tree.frame)) return false;\n const frame = tree.frame;\n if (\n typeof frame.id !== \"string\" ||\n typeof frame.loaderId !== \"string\" ||\n typeof frame.url !== \"string\" ||\n (frame.securityOrigin !== undefined && typeof frame.securityOrigin !== \"string\")\n ) {\n return false;\n }\n frames.push({\n id: frame.id,\n loaderId: frame.loaderId,\n url: frame.url,\n ...(frame.securityOrigin === undefined ? {} : { securityOrigin: frame.securityOrigin }),\n });\n if (tree.childFrames === undefined) return true;\n return Array.isArray(tree.childFrames) && tree.childFrames.every(visit);\n };\n return visit(value.frameTree) ? frames : undefined;\n}\n\nfunction frameNavigationChangesIdentity(value: unknown, frameId: string, documentId: string) {\n if (!isRecord(value) || !isRecord(value.frame)) {\n throw new Error(\"Chrome sent a malformed Page.frameNavigated event\");\n }\n if (typeof value.frame.id !== \"string\" || typeof value.frame.loaderId !== \"string\") {\n throw new Error(\"Chrome sent a malformed Page.frameNavigated event\");\n }\n return value.frame.id === frameId && value.frame.loaderId !== documentId;\n}\n\nfunction toolChangeMatchesIdentity(value: unknown, expected: { frameId: string; toolName: string }) {\n if (!isRecord(value) || !Array.isArray(value.tools)) {\n throw new Error(\"Chrome sent a malformed WebMCP tool-change event\");\n }\n return value.tools.some((tool) => {\n if (!isRecord(tool) || typeof tool.frameId !== \"string\" || typeof tool.name !== \"string\") {\n throw new Error(\"Chrome sent a malformed WebMCP tool-change event\");\n }\n return tool.frameId === expected.frameId && tool.name === expected.toolName;\n });\n}\n\nfunction parseInvocationId(value: unknown) {\n return isRecord(value) && typeof value.invocationId === \"string\" ? value.invocationId : undefined;\n}\n\nfunction parseToolResponded(value: unknown): WebMcpInvocationResponse | undefined {\n if (\n !isRecord(value) ||\n typeof value.invocationId !== \"string\" ||\n !([\"Canceled\", \"Completed\", \"Error\"] as const).includes(value.status as never) ||\n (value.errorText !== undefined && typeof value.errorText !== \"string\")\n ) {\n return undefined;\n }\n return {\n invocationId: value.invocationId,\n status: value.status as WebMcpInvocationResponse[\"status\"],\n ...(value.output === undefined ? {} : { output: value.output }),\n ...(value.errorText === undefined ? {} : { errorText: value.errorText }),\n ...(value.exception === undefined ? {} : { exception: value.exception }),\n };\n}\n\nfunction withDeadline(signal: AbortSignal) {\n return AbortSignal.any([signal, AbortSignal.timeout(DEFAULT_TIMEOUT_MS)]);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n", "import { getPage } from \"../cdp-client.js\";\nimport { type DevToolsPage, webMcpOperationIsCurrent } from \"../runtime.js\";\nimport {\n MAX_WEBMCP_TOOLS,\n normalizeWebMcpOutput,\n normalizeWebMcpTool,\n requireMatchingWebMcpTool,\n type WebMcpToolDescriptor,\n type WebMcpToolIdentity,\n webMcpErrorMessage,\n} from \"./policy.js\";\nimport {\n cancelWebMcpInvocation,\n connectWebMcpPage,\n disableWebMcp,\n enableWebMcp,\n enableWebMcpIdentityTracking,\n invokeWebMcpTool,\n readWebMcpFrames,\n requireWebMcpDomain,\n type WebMcpFrame,\n type WebMcpProtocolTool,\n watchWebMcpIdentity,\n} from \"./protocol.js\";\n\nexport interface WebMcpOperationIdentity {\n owner: object;\n sessionGeneration: number;\n signal: AbortSignal;\n webMcpGeneration: number;\n}\n\nexport interface WebMcpInvocationResult {\n invocationId: string;\n output: unknown;\n tool: WebMcpToolDescriptor;\n}\n\nexport async function discoverWebMcpTools(page: DevToolsPage, operation: WebMcpOperationIdentity) {\n assertOperationCurrent(operation);\n await requireWebMcpDomain(operation.signal, operation.owner);\n assertOperationCurrent(operation);\n const client = await connectWebMcpPage(page, operation.signal);\n try {\n const tools = await readInventory(client, page, operation);\n await requireStablePage(client, page, tools, operation);\n return tools;\n } finally {\n await disableWebMcp(client);\n client.close();\n }\n}\n\nexport async function invokeDiscoveredWebMcpTool(\n page: DevToolsPage,\n expected: WebMcpToolIdentity,\n input: Record<string, unknown>,\n operation: WebMcpOperationIdentity,\n): Promise<WebMcpInvocationResult> {\n assertOperationCurrent(operation);\n await requireWebMcpDomain(operation.signal, operation.owner);\n assertOperationCurrent(operation);\n const client = await connectWebMcpPage(page, operation.signal);\n try {\n await enableWebMcpIdentityTracking(client, operation.signal);\n assertOperationCurrent(operation);\n const tools = await readInventory(client, page, operation);\n const tool = requireMatchingWebMcpTool(tools, expected);\n const identityWatch = watchWebMcpIdentity(\n client,\n { documentId: tool.documentId, frameId: tool.frameId, toolName: tool.name },\n operation.signal,\n );\n const guardedOperation = { ...operation, signal: identityWatch.signal };\n try {\n await requireStablePage(client, page, [tool], guardedOperation);\n assertOperationCurrent(guardedOperation);\n const response = await invokeWebMcpTool(\n client,\n { frameId: tool.frameId, toolName: tool.name, input },\n guardedOperation.signal,\n (invocationId) => cancelWebMcpInvocation(page, invocationId),\n );\n assertOperationCurrent(guardedOperation);\n if (response.status === \"Canceled\") {\n throw new DOMException(\"Chrome canceled the WebMCP tool invocation.\", \"AbortError\");\n }\n if (response.status === \"Error\") {\n throw new Error(\n `WebMCP tool failed: ${webMcpErrorMessage(response.errorText ?? remoteExceptionText(response.exception))}`,\n );\n }\n return {\n invocationId: response.invocationId,\n output: normalizeWebMcpOutput(response.output ?? null),\n tool,\n };\n } finally {\n await identityWatch.dispose();\n }\n } finally {\n await disableWebMcp(client);\n client.close();\n }\n}\n\nasync function readInventory(\n client: Awaited<ReturnType<typeof connectWebMcpPage>>,\n page: DevToolsPage,\n operation: WebMcpOperationIdentity,\n) {\n const framesBefore = await readWebMcpFrames(client, operation.signal);\n assertOperationCurrent(operation);\n const protocolTools = await enableWebMcp(client, operation.signal);\n assertOperationCurrent(operation);\n if (protocolTools.length > MAX_WEBMCP_TOOLS) {\n throw new Error(`WebMCP page exposes more than ${MAX_WEBMCP_TOOLS} tools.`);\n }\n const framesAfter = await readWebMcpFrames(client, operation.signal);\n assertOperationCurrent(operation);\n requireStableInventoryDocuments(protocolTools, framesBefore, framesAfter);\n return normalizeInventory(protocolTools, framesAfter, page, operation);\n}\n\nfunction requireStableInventoryDocuments(\n tools: readonly WebMcpProtocolTool[],\n before: readonly WebMcpFrame[],\n after: readonly WebMcpFrame[],\n) {\n const beforeLoaders = new Map(before.map((frame) => [frame.id, frame.loaderId]));\n const afterLoaders = new Map(after.map((frame) => [frame.id, frame.loaderId]));\n for (const frameId of new Set(tools.map((tool) => tool.frameId))) {\n const beforeLoader = beforeLoaders.get(frameId);\n const afterLoader = afterLoaders.get(frameId);\n if (!beforeLoader || !afterLoader || beforeLoader !== afterLoader) {\n throw new Error(\"A WebMCP frame document changed while Chrome was publishing its tool inventory.\");\n }\n }\n}\n\nfunction normalizeInventory(\n protocolTools: readonly WebMcpProtocolTool[],\n frames: readonly WebMcpFrame[],\n page: DevToolsPage,\n operation: WebMcpOperationIdentity,\n) {\n const frameDocuments = new Map(\n frames.map((frame) => [frame.id, { documentId: frame.loaderId, origin: frameOrigin(frame) }]),\n );\n const tools = protocolTools.map((tool) => {\n const frame = frameDocuments.get(tool.frameId);\n if (!frame) {\n throw new Error(`WebMCP tool ${webMcpErrorMessage(tool.name)} belongs to an unknown frame.`);\n }\n return normalizeWebMcpTool(tool, {\n documentId: frame.documentId,\n frameOrigin: frame.origin,\n pageId: page.id,\n pageUrl: page.url,\n sessionGeneration: generationToken(operation),\n });\n });\n const identities = new Set<string>();\n for (const tool of tools) {\n const key = `${tool.frameId}\\u0000${tool.name}`;\n if (identities.has(key)) {\n throw new Error(\n `WebMCP tool identity is duplicated: ${webMcpErrorMessage(tool.name)} in frame ${webMcpErrorMessage(tool.frameId)}.`,\n );\n }\n identities.add(key);\n }\n return tools;\n}\n\nasync function requireStablePage(\n client: Awaited<ReturnType<typeof connectWebMcpPage>>,\n page: DevToolsPage,\n tools: readonly WebMcpToolDescriptor[],\n operation: WebMcpOperationIdentity,\n) {\n const current = await getPage(page.id, {\n sessionOwner: operation.owner,\n signal: operation.signal,\n });\n assertOperationCurrent(operation);\n if (\n current.url !== page.url ||\n current.webSocketDebuggerUrl !== page.webSocketDebuggerUrl ||\n current.type !== page.type\n ) {\n throw new Error(\"The Chrome page navigated or was replaced during the WebMCP operation.\");\n }\n const finalFrames = await readWebMcpFrames(client, operation.signal);\n assertOperationCurrent(operation);\n const finalDocuments = new Map(finalFrames.map((frame) => [frame.id, frame.loaderId]));\n for (const tool of tools) {\n if (finalDocuments.get(tool.frameId) !== tool.documentId) {\n throw new Error(\"A WebMCP frame document changed during the final page identity check.\");\n }\n }\n}\n\nfunction assertOperationCurrent(operation: WebMcpOperationIdentity) {\n operation.signal.throwIfAborted();\n if (!webMcpOperationIsCurrent(operation)) {\n throw new DOMException(\"The WebMCP operation became stale.\", \"AbortError\");\n }\n}\n\nfunction generationToken(operation: WebMcpOperationIdentity) {\n return `${operation.sessionGeneration}:${operation.webMcpGeneration}`;\n}\n\nfunction frameOrigin(frame: WebMcpFrame) {\n if (frame.securityOrigin && frame.securityOrigin !== \"://\") return frame.securityOrigin;\n try {\n return new URL(frame.url).origin;\n } catch {\n throw new Error(`Chrome returned an invalid WebMCP frame URL: ${webMcpErrorMessage(frame.url)}`);\n }\n}\n\nfunction remoteExceptionText(value: unknown) {\n if (typeof value === \"object\" && value !== null) {\n const exception = value as { description?: unknown; value?: unknown };\n if (typeof exception.description === \"string\") return exception.description;\n if (typeof exception.value === \"string\") return exception.value;\n }\n return \"The page reported an unknown tool error.\";\n}\n", "import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { managedBrowserForOwner } from \"../browser-manager.js\";\nimport { getPage, resolvePage, textResult } from \"../cdp-client.js\";\nimport {\n beginWebMcpOperation,\n currentWebMcpGeneration,\n webMcpEnabled,\n webMcpOperationIsCurrent,\n webMcpSessionSignal,\n} from \"../runtime.js\";\nimport { discoverWebMcpTools, invokeDiscoveredWebMcpTool } from \"./discovery.js\";\nimport {\n boundedWebMcpDiscovery,\n boundedWebMcpJson,\n normalizeWebMcpInput,\n requireMatchingWebMcpTool,\n sanitizeWebMcpDisplay,\n validateWebMcpInput,\n type WebMcpToolIdentity,\n webMcpConfirmationMessage,\n webMcpErrorMessage,\n webMcpIdentity,\n} from \"./policy.js\";\n\ninterface ListInput {\n pageId?: string;\n}\n\ninterface CallInput extends Omit<WebMcpToolIdentity, \"name\"> {\n input: Record<string, unknown>;\n toolName: string;\n}\n\nexport async function executeWebMcpListTool(\n params: ListInput,\n toolSignal: AbortSignal | undefined,\n ctx: ExtensionContext,\n) {\n try {\n requireWebMcpEnabled(ctx.sessionManager);\n const preflightGeneration = currentWebMcpGeneration(ctx.sessionManager);\n const preflightSignal = combinedSignal(ctx.sessionManager, toolSignal);\n preflightSignal.throwIfAborted();\n const page = await resolvePage(params.pageId, {\n sessionOwner: ctx.sessionManager,\n signal: preflightSignal,\n });\n preflightSignal.throwIfAborted();\n requireCurrentPreflight(ctx.sessionManager, preflightGeneration);\n const operation = beginWebMcpOperation(ctx.sessionManager, toolSignal);\n try {\n const tools = await discoverWebMcpTools(page, operation);\n assertCurrent(operation);\n const published = boundedWebMcpDiscovery({ id: page.id, title: page.title, url: page.url }, tools);\n return textResult(published.text, {\n page: { id: page.id, url: page.url },\n toolCount: tools.length,\n publishedToolCount: published.included.length,\n truncated: published.truncated,\n identities: published.included.map(webMcpIdentity),\n });\n } finally {\n operation.dispose();\n }\n } catch (error) {\n throw safeToolError(error);\n }\n}\n\nexport async function executeWebMcpCallTool(\n params: CallInput,\n toolSignal: AbortSignal | undefined,\n ctx: ExtensionContext,\n) {\n try {\n requireWebMcpEnabled(ctx.sessionManager);\n if (!ctx.hasUI || (ctx.mode !== \"tui\" && ctx.mode !== \"rpc\")) {\n throw new Error(\n \"chrome_devtools_webmcp_call_tool requires observable confirmation in TUI or RPC mode and is unavailable in print or JSON mode.\",\n );\n }\n const input = normalizeWebMcpInput(params.input);\n const expected = expectedIdentity(params);\n const preflightGeneration = currentWebMcpGeneration(ctx.sessionManager);\n const preflightSignal = combinedSignal(ctx.sessionManager, toolSignal);\n preflightSignal.throwIfAborted();\n const page = await getPage(params.pageId, {\n sessionOwner: ctx.sessionManager,\n signal: preflightSignal,\n });\n preflightSignal.throwIfAborted();\n requireCurrentPreflight(ctx.sessionManager, preflightGeneration);\n const operation = beginWebMcpOperation(ctx.sessionManager, toolSignal);\n try {\n const discovered = await discoverWebMcpTools(page, operation);\n const current = requireMatchingWebMcpTool(discovered, expected);\n const validatedInput = validateWebMcpInput(current.inputSchema, input);\n assertCurrent(operation);\n const confirmed = await ctx.ui.confirm(\n `Allow WebMCP tool: ${sanitizeWebMcpDisplay(current.name, 256)}`,\n webMcpConfirmationMessage(current, validatedInput, usesManagedProfile(ctx.sessionManager)),\n { signal: operation.signal },\n );\n assertCurrent(operation);\n if (!confirmed) {\n throw new DOMException(\"WebMCP tool call cancelled by the user.\", \"AbortError\");\n }\n const invocation = await invokeDiscoveredWebMcpTool(page, expected, validatedInput, operation);\n assertCurrent(operation);\n const published = boundedWebMcpJson({\n status: \"completed\",\n tool: webMcpIdentity(invocation.tool),\n output: invocation.output,\n });\n return textResult(published.text, {\n invocationId: invocation.invocationId,\n tool: webMcpIdentity(invocation.tool),\n truncated: published.truncated,\n output: published.text,\n });\n } finally {\n operation.dispose();\n }\n } catch (error) {\n throw safeToolError(error);\n }\n}\n\nfunction requireWebMcpEnabled(owner: object) {\n if (!webMcpEnabled(owner)) {\n throw new Error(\n \"WebMCP is disabled. Enable the experimental user setting in /chrome-devtools settings, then make the WebMCP gateway tools available.\",\n );\n }\n}\n\nfunction combinedSignal(owner: object, toolSignal: AbortSignal | undefined) {\n const sessionSignal = webMcpSessionSignal(owner);\n return toolSignal ? AbortSignal.any([toolSignal, sessionSignal]) : sessionSignal;\n}\n\nfunction requireCurrentPreflight(owner: object, generation: number) {\n requireWebMcpEnabled(owner);\n if (generation !== currentWebMcpGeneration(owner)) {\n throw new DOMException(\"The WebMCP operation became stale during page resolution.\", \"AbortError\");\n }\n}\n\nfunction expectedIdentity(params: CallInput): WebMcpToolIdentity {\n return {\n sessionGeneration: params.sessionGeneration,\n pageId: params.pageId,\n documentId: params.documentId,\n frameId: params.frameId,\n frameOrigin: params.frameOrigin,\n name: params.toolName,\n schemaDigest: params.schemaDigest,\n };\n}\n\nfunction assertCurrent(operation: ReturnType<typeof beginWebMcpOperation>) {\n operation.signal.throwIfAborted();\n if (!webMcpOperationIsCurrent(operation)) {\n throw new DOMException(\"The WebMCP operation became stale.\", \"AbortError\");\n }\n}\n\nfunction usesManagedProfile(owner: object) {\n const managedBrowser = managedBrowserForOwner(owner);\n return Boolean(managedBrowser?.ready && !managedBrowser.exited);\n}\n\nfunction safeToolError(error: unknown) {\n const message = webMcpErrorMessage(error);\n if (error instanceof DOMException && error.name === \"AbortError\") {\n return new DOMException(message, \"AbortError\");\n }\n return new Error(message);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["frameOrigin", "publication", "isRecord"]
|
|
7
|
+
}
|
package/dist/index.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
setActivePageId,
|
|
10
10
|
textResult,
|
|
11
11
|
withCdp
|
|
12
|
-
} from "./chunks/chunk-
|
|
12
|
+
} from "./chunks/chunk-4KMN4SFF.js";
|
|
13
13
|
import {
|
|
14
14
|
allChromeDevtoolsTools,
|
|
15
15
|
availableChromeDevtoolsTools,
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
supportsNativeDeferredToolLoading,
|
|
26
26
|
updateChromeDevtoolsTools,
|
|
27
27
|
waitForChromeDevtoolsSettings
|
|
28
|
-
} from "./chunks/chunk-
|
|
28
|
+
} from "./chunks/chunk-MZCGM6D3.js";
|
|
29
29
|
import {
|
|
30
30
|
CHROME_DEVTOOLS_TOOL_NAMES,
|
|
31
31
|
WEBMCP_TOOL_NAMES,
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
syncManagedBrowserSettings,
|
|
41
41
|
waitForSettingsWrites,
|
|
42
42
|
webMcpEnabled
|
|
43
|
-
} from "./chunks/chunk-
|
|
43
|
+
} from "./chunks/chunk-F5VG35UI.js";
|
|
44
44
|
|
|
45
45
|
// src/tools.ts
|
|
46
46
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
@@ -184,9 +184,7 @@ async function ensureSafeScreenshotParent(resolvedPath) {
|
|
|
184
184
|
const parentPath = dirname(resolvedPath.path);
|
|
185
185
|
const rootPath = selectAllowedRoot(parentPath, resolvedPath.allowedRoots);
|
|
186
186
|
if (!rootPath) {
|
|
187
|
-
throw new Error(
|
|
188
|
-
"Screenshot savePath parent must stay inside the current working directory or OS temp directory."
|
|
189
|
-
);
|
|
187
|
+
throw new Error("Screenshot savePath parent must stay inside the current working directory or OS temp directory.");
|
|
190
188
|
}
|
|
191
189
|
const realRootPath = await realpath(rootPath);
|
|
192
190
|
let currentPath = rootPath;
|
|
@@ -237,17 +235,13 @@ async function assertSafeScreenshotTargetPath(resolvedPath) {
|
|
|
237
235
|
const realParent = await realpath(dirname(resolvedPath.path));
|
|
238
236
|
const realTargetPath = join(realParent, basename(resolvedPath.path));
|
|
239
237
|
if (!realAllowedRoots.some((root) => isPathInsideRoot(realTargetPath, root))) {
|
|
240
|
-
throw new Error(
|
|
241
|
-
"Screenshot savePath resolves outside the current working directory or OS temp directory."
|
|
242
|
-
);
|
|
238
|
+
throw new Error("Screenshot savePath resolves outside the current working directory or OS temp directory.");
|
|
243
239
|
}
|
|
244
240
|
}
|
|
245
241
|
async function assertPathWithinRealRoot(path, realRootPath) {
|
|
246
242
|
const realPath = await realpath(path);
|
|
247
243
|
if (!isPathInsideRoot(realPath, realRootPath)) {
|
|
248
|
-
throw new Error(
|
|
249
|
-
"Screenshot savePath parent resolves outside the current working directory or OS temp directory."
|
|
250
|
-
);
|
|
244
|
+
throw new Error("Screenshot savePath parent resolves outside the current working directory or OS temp directory.");
|
|
251
245
|
}
|
|
252
246
|
}
|
|
253
247
|
async function writeScreenshotFileSafely(resolvedPath, pngBytes, signal) {
|
|
@@ -347,9 +341,7 @@ var navigateTool = defineTool({
|
|
|
347
341
|
description: "Navigate a Chrome page to a URL through Chrome DevTools Protocol, creating a page first if none is available.",
|
|
348
342
|
parameters: Type.Object({
|
|
349
343
|
url: Type.String({ description: "URL to navigate to." }),
|
|
350
|
-
pageId: Type.Optional(
|
|
351
|
-
Type.String({ description: "Optional page id. Defaults to selected or first page." })
|
|
352
|
-
)
|
|
344
|
+
pageId: Type.Optional(Type.String({ description: "Optional page id. Defaults to selected or first page." }))
|
|
353
345
|
}),
|
|
354
346
|
renderCall: renderToolCall("navigate"),
|
|
355
347
|
renderResult: renderTextResult,
|
|
@@ -379,9 +371,7 @@ var evaluateTool = defineTool({
|
|
|
379
371
|
description: "Evaluate JavaScript in a Chrome page through Chrome DevTools Protocol.",
|
|
380
372
|
parameters: Type.Object({
|
|
381
373
|
expression: Type.String({ description: "JavaScript expression to evaluate." }),
|
|
382
|
-
pageId: Type.Optional(
|
|
383
|
-
Type.String({ description: "Optional page id. Defaults to selected or first page." })
|
|
384
|
-
),
|
|
374
|
+
pageId: Type.Optional(Type.String({ description: "Optional page id. Defaults to selected or first page." })),
|
|
385
375
|
awaitPromise: Type.Optional(
|
|
386
376
|
Type.Boolean({ description: "Whether to await a returned Promise. Defaults to true." })
|
|
387
377
|
)
|
|
@@ -423,7 +413,7 @@ var webMcpListToolsTool = defineTool({
|
|
|
423
413
|
renderResult: renderTextResult,
|
|
424
414
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
425
415
|
return withStatus(ctx, "list WebMCP tools", async () => {
|
|
426
|
-
const implementation = await import("./chunks/tools-
|
|
416
|
+
const implementation = await import("./chunks/tools-6R7Z6HWJ.js");
|
|
427
417
|
return implementation.executeWebMcpListTool(params, signal, ctx);
|
|
428
418
|
});
|
|
429
419
|
}
|
|
@@ -465,7 +455,7 @@ var webMcpCallTool = defineTool({
|
|
|
465
455
|
renderResult: renderTextResult,
|
|
466
456
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
467
457
|
return withStatus(ctx, "call WebMCP tool", async () => {
|
|
468
|
-
const implementation = await import("./chunks/tools-
|
|
458
|
+
const implementation = await import("./chunks/tools-6R7Z6HWJ.js");
|
|
469
459
|
return implementation.executeWebMcpCallTool(params, signal, ctx);
|
|
470
460
|
});
|
|
471
461
|
}
|
|
@@ -475,12 +465,8 @@ var screenshotTool = defineTool({
|
|
|
475
465
|
label: "Chrome DevTools: Screenshot",
|
|
476
466
|
description: "Capture a PNG screenshot from a Chrome page through Chrome DevTools Protocol.",
|
|
477
467
|
parameters: Type.Object({
|
|
478
|
-
pageId: Type.Optional(
|
|
479
|
-
|
|
480
|
-
),
|
|
481
|
-
fullPage: Type.Optional(
|
|
482
|
-
Type.Boolean({ description: "Capture the full document, not just the viewport." })
|
|
483
|
-
),
|
|
468
|
+
pageId: Type.Optional(Type.String({ description: "Optional page id. Defaults to selected or first page." })),
|
|
469
|
+
fullPage: Type.Optional(Type.Boolean({ description: "Capture the full document, not just the viewport." })),
|
|
484
470
|
savePath: Type.Optional(
|
|
485
471
|
Type.String({
|
|
486
472
|
description: "Screenshot is always saved as a PNG file. Optional output path; omitted defaults to a unique temp file. Relative paths resolve from the current working directory. A single leading @ is stripped to match Pi file-mention paths. Existing regular files are replaced."
|
|
@@ -609,10 +595,7 @@ function chromeDevtools(pi) {
|
|
|
609
595
|
configureChromeDevtoolsToolExposure(pi, availableTools, ctx.model);
|
|
610
596
|
});
|
|
611
597
|
pi.on("model_select", (event, ctx) => {
|
|
612
|
-
invalidateWebMcpOperations(
|
|
613
|
-
ctx.sessionManager,
|
|
614
|
-
"Chrome DevTools model and tool exposure changed"
|
|
615
|
-
);
|
|
598
|
+
invalidateWebMcpOperations(ctx.sessionManager, "Chrome DevTools model and tool exposure changed");
|
|
616
599
|
if (!supportsNativeDeferredToolLoading(event.model)) {
|
|
617
600
|
requireEagerChromeDevtoolsToolExposure(pi);
|
|
618
601
|
}
|
|
@@ -656,7 +639,7 @@ async function handleChromeDevtoolsCommand(pi, args, ctx, generation) {
|
|
|
656
639
|
if (!ctx.hasUI || ctx.mode !== "tui" && ctx.mode !== "rpc") {
|
|
657
640
|
throw new Error("/chrome-devtools settings requires TUI or RPC mode");
|
|
658
641
|
}
|
|
659
|
-
const { showChromeDevtoolsBrowserSettings } = await import("./chunks/browser-settings-menu-
|
|
642
|
+
const { showChromeDevtoolsBrowserSettings } = await import("./chunks/browser-settings-menu-SR7KLZT6.js");
|
|
660
643
|
if (generation !== state.sessionGeneration) return;
|
|
661
644
|
await showChromeDevtoolsBrowserSettings(pi, ctx, generation);
|
|
662
645
|
return;
|
|
@@ -665,18 +648,13 @@ async function handleChromeDevtoolsCommand(pi, args, ctx, generation) {
|
|
|
665
648
|
if (!ctx.hasUI || ctx.mode !== "tui" && ctx.mode !== "rpc") {
|
|
666
649
|
throw new Error("/chrome-devtools tools requires TUI or RPC mode");
|
|
667
650
|
}
|
|
668
|
-
const { showChromeDevtoolsToolWorkflow } = await import("./chunks/menu-
|
|
651
|
+
const { showChromeDevtoolsToolWorkflow } = await import("./chunks/menu-YR4VRT7D.js");
|
|
669
652
|
if (generation !== state.sessionGeneration) return;
|
|
670
653
|
await showChromeDevtoolsToolWorkflow(pi, ctx, generation);
|
|
671
654
|
return;
|
|
672
655
|
}
|
|
673
656
|
case "enable":
|
|
674
|
-
await updateChromeDevtoolsTools(
|
|
675
|
-
pi,
|
|
676
|
-
ctx,
|
|
677
|
-
allChromeDevtoolsTools(ctx.sessionManager),
|
|
678
|
-
"made all available"
|
|
679
|
-
);
|
|
657
|
+
await updateChromeDevtoolsTools(pi, ctx, allChromeDevtoolsTools(ctx.sessionManager), "made all available");
|
|
680
658
|
return;
|
|
681
659
|
case "disable":
|
|
682
660
|
await updateChromeDevtoolsTools(pi, ctx, [], "made all unavailable");
|
|
@@ -701,7 +679,7 @@ async function showMenu(pi, ctx, generation) {
|
|
|
701
679
|
if (!ctx.hasUI || ctx.mode !== "tui" && ctx.mode !== "rpc") {
|
|
702
680
|
throw new Error("/chrome-devtools menu requires TUI or RPC mode; use a direct subcommand");
|
|
703
681
|
}
|
|
704
|
-
const { showChromeDevtoolsMenu } = await import("./chunks/menu-
|
|
682
|
+
const { showChromeDevtoolsMenu } = await import("./chunks/menu-YR4VRT7D.js");
|
|
705
683
|
if (generation !== state.sessionGeneration) return;
|
|
706
684
|
await showChromeDevtoolsMenu(pi, ctx, generation);
|
|
707
685
|
}
|
|
@@ -724,9 +702,7 @@ function parseCommand(args) {
|
|
|
724
702
|
function commandCompletions(prefix) {
|
|
725
703
|
const normalized = prefix.trimStart().toLowerCase();
|
|
726
704
|
if (/\s/.test(normalized)) return null;
|
|
727
|
-
const matches = COMMAND_COMPLETIONS.filter(
|
|
728
|
-
(completion) => completion.value.startsWith(normalized)
|
|
729
|
-
);
|
|
705
|
+
const matches = COMMAND_COMPLETIONS.filter((completion) => completion.value.startsWith(normalized));
|
|
730
706
|
return matches.length > 0 ? matches : null;
|
|
731
707
|
}
|
|
732
708
|
export {
|