@narumitw/pi-chrome-devtools 0.53.0 → 0.53.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +88 -230
  2. package/dist/chunks/{browser-settings-menu-N5O65I7S.js → browser-settings-menu-IMB6HXSU.js} +5 -3
  3. package/dist/chunks/browser-settings-menu-IMB6HXSU.js.map +7 -0
  4. package/dist/chunks/{chunk-RTECHAEZ.js → chunk-GTTYS5GT.js} +20 -9
  5. package/dist/chunks/chunk-GTTYS5GT.js.map +7 -0
  6. package/dist/chunks/{chunk-B7B63PWB.js → chunk-LLXOCRNF.js} +50 -30
  7. package/dist/chunks/chunk-LLXOCRNF.js.map +7 -0
  8. package/dist/chunks/{chunk-GVBXT3FB.js → chunk-SRT3UUIP.js} +117 -73
  9. package/dist/chunks/chunk-SRT3UUIP.js.map +7 -0
  10. package/dist/chunks/{menu-UBHW6UP2.js → menu-UJETYMSB.js} +4 -4
  11. package/dist/chunks/{tools-V7OR5KJ3.js → tools-6P7EUX37.js} +49 -30
  12. package/dist/chunks/tools-6P7EUX37.js.map +7 -0
  13. package/dist/index.ts +21 -18
  14. package/dist/index.ts.map +2 -2
  15. package/docs/browser-setup.md +147 -0
  16. package/package.json +7 -7
  17. package/src/browser-manager.ts +138 -72
  18. package/src/browser-settings-menu.ts +2 -1
  19. package/src/cdp-client.ts +18 -7
  20. package/src/chrome-devtools.ts +8 -1
  21. package/src/display.ts +38 -0
  22. package/src/render.ts +6 -7
  23. package/src/tool-selector.ts +21 -32
  24. package/src/tools.ts +5 -5
  25. package/src/webmcp/policy.ts +14 -7
  26. package/src/webmcp/protocol.ts +33 -21
  27. package/dist/chunks/browser-settings-menu-N5O65I7S.js.map +0 -7
  28. package/dist/chunks/chunk-B7B63PWB.js.map +0 -7
  29. package/dist/chunks/chunk-GVBXT3FB.js.map +0 -7
  30. package/dist/chunks/chunk-RTECHAEZ.js.map +0 -7
  31. package/dist/chunks/tools-V7OR5KJ3.js.map +0 -7
  32. /package/dist/chunks/{menu-UBHW6UP2.js.map → menu-UJETYMSB.js.map} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/cdp-client.ts"],
4
+ "sourcesContent": ["import {\n\tdevToolsEndpoint,\n\tensureDevToolsEndpoint,\n\tfetchDevToolsJson,\n\tformatPageListItem,\n\tlaunchHint,\n\twithEndpointRetry,\n} from \"./browser-manager.js\";\nimport {\n\tDEFAULT_ENDPOINT_WAIT_MS,\n\tDEFAULT_TIMEOUT_MS,\n\ttype DevToolsPage,\n\tstate,\n} from \"./runtime.js\";\n\ninterface CdpResponse<T = unknown> {\n\terror?: { code: number; data?: unknown; message: string };\n\tid: number;\n\tresult?: T;\n}\n\ninterface CdpEvent {\n\tmethod: string;\n\tparams?: unknown;\n}\n\ninterface PendingRequest {\n\tcleanup: () => void;\n\treject: (reason: unknown) => void;\n\tresolve: (value: unknown) => void;\n}\n\ninterface EventWaiter<T = unknown> {\n\tcleanup: () => void;\n\tmethod: string;\n\tpredicate: (params: unknown) => params is T;\n\treject: (reason: unknown) => void;\n\tresolve: (params: T) => void;\n}\n\nexport type CdpWebSocketConstructor = new (url: string | URL) => WebSocket;\n\nexport interface CdpOperationOptions {\n\tsignal?: AbortSignal;\n\ttimeoutMs?: number;\n}\n\nexport interface CdpConnectOptions extends CdpOperationOptions {\n\twebSocketConstructor?: CdpWebSocketConstructor;\n}\n\nconst MAX_BUFFERED_EVENTS_PER_METHOD = 32;\nconst MAX_CDP_MESSAGE_BYTES = 8 * 1024 * 1024;\nconst activePageIds = new WeakMap<object, string>();\n\ninterface PageOperationOptions {\n\tsessionOwner?: object;\n\tsignal?: AbortSignal;\n\twaitMs?: number;\n}\n\nexport async function listPages(options: PageOperationOptions = {}) {\n\tconst waitMs = options.waitMs ?? DEFAULT_ENDPOINT_WAIT_MS;\n\tawait ensureDevToolsEndpoint(waitMs, options.signal, options.sessionOwner);\n\treturn withEndpointRetry(\n\t\tasync () => {\n\t\t\tconst pages = await fetchDevToolsJson<DevToolsPage[]>(\n\t\t\t\t\"/json/list\",\n\t\t\t\t{ signal: options.signal },\n\t\t\t\toptions.sessionOwner,\n\t\t\t);\n\t\t\treturn pages.filter((page) => page.type === \"page\" && page.webSocketDebuggerUrl);\n\t\t},\n\t\twaitMs,\n\t\toptions.signal,\n\t);\n}\n\nexport async function getPage(pageId: string, options: PageOperationOptions = {}) {\n\tconst pages = await listPages(options);\n\treturn requirePage(pageId, pages);\n}\n\nexport async function resolvePage(pageId?: string, options: PageOperationOptions = {}) {\n\tconst pages = await listPages(options);\n\tif (pageId) return requirePage(pageId, pages);\n\n\tconst page = resolveDefaultPage(pages, options.sessionOwner);\n\tif (!page) {\n\t\tthrow new Error(\n\t\t\t[\n\t\t\t\t`No Chrome pages found at ${devToolsEndpoint(options.sessionOwner)}.`,\n\t\t\t\t\"Use chrome_devtools_navigate with a URL to create a page, or open a Chrome tab manually.\",\n\t\t\t\tlaunchHint(options.sessionOwner),\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t}\n\n\treturn page;\n}\n\nexport async function resolvePageForNavigation(\n\tpageId?: string,\n\toptions: PageOperationOptions = {},\n) {\n\tconst pages = await listPages(options);\n\tif (pageId) return { created: false, page: requirePage(pageId, pages) };\n\n\tconst page = resolveDefaultPage(pages, options.sessionOwner);\n\tif (page) return { created: false, page };\n\n\treturn { created: true, page: await createPage(\"about:blank\", options) };\n}\n\nfunction resolveDefaultPage(pages: DevToolsPage[], owner?: object) {\n\tconst activePageId = owner ? activePageIds.get(owner) : state.activePageId;\n\tif (!activePageId) return pages[0];\n\n\tconst activePage = pages.find((candidate) => candidate.id === activePageId);\n\tif (activePage) return activePage;\n\n\tsetActivePageId(owner, undefined);\n\treturn pages[0];\n}\n\nexport function setActivePageId(owner: object | undefined, pageId: string | undefined) {\n\tif (!owner) {\n\t\tstate.activePageId = pageId;\n\t\treturn;\n\t}\n\tif (pageId) activePageIds.set(owner, pageId);\n\telse activePageIds.delete(owner);\n}\n\nfunction requirePage(pageId: string, pages: DevToolsPage[]) {\n\tconst page = pages.find((candidate) => candidate.id === pageId);\n\tif (page) return page;\n\n\tconst availablePages = pages.map(formatPageListItem).join(\"\\n\");\n\tthrow new Error(\n\t\t[\n\t\t\t`Chrome DevTools page not found: ${pageId}.`,\n\t\t\tavailablePages\n\t\t\t\t? `Available pages:\\n${availablePages}`\n\t\t\t\t: \"No inspectable Chrome pages are currently available.\",\n\t\t].join(\"\\n\"),\n\t);\n}\n\nexport async function createPage(url: string, options: PageOperationOptions = {}) {\n\tconst waitMs = options.waitMs ?? DEFAULT_ENDPOINT_WAIT_MS;\n\tawait ensureDevToolsEndpoint(waitMs, options.signal, options.sessionOwner);\n\tconst page = await withEndpointRetry(\n\t\t() =>\n\t\t\tfetchDevToolsJson<DevToolsPage>(\n\t\t\t\t`/json/new?${encodeURIComponent(url)}`,\n\t\t\t\t{ method: \"PUT\", signal: options.signal },\n\t\t\t\toptions.sessionOwner,\n\t\t\t),\n\t\twaitMs,\n\t\toptions.signal,\n\t);\n\tif (page.type !== \"page\" || !page.webSocketDebuggerUrl) {\n\t\tthrow new Error(\"Chrome DevTools created a target that is not an inspectable page.\");\n\t}\n\n\treturn page;\n}\n\nexport function formatPage(page: DevToolsPage) {\n\treturn {\n\t\tid: page.id,\n\t\ttype: page.type,\n\t\ttitle: page.title,\n\t\turl: page.url,\n\t};\n}\n\nexport function textResult<T>(text: string, details: T) {\n\treturn {\n\t\tcontent: [{ type: \"text\" as const, text }],\n\t\tdetails,\n\t};\n}\n\nexport async function withCdp<T>(\n\tpage: DevToolsPage,\n\tcallback: (client: CdpClient) => Promise<T>,\n\toptions: CdpConnectOptions = {},\n) {\n\tif (!page.webSocketDebuggerUrl) throw new Error(`Page has no webSocketDebuggerUrl: ${page.id}`);\n\n\tconst client = await CdpClient.connect(page.webSocketDebuggerUrl, options);\n\ttry {\n\t\treturn await callback(client);\n\t} finally {\n\t\tclient.close();\n\t}\n}\n\nexport class CdpClient {\n\t#closed = false;\n\t#eventBuffers = new Map<string, unknown[]>();\n\t#eventWaiters = new Set<EventWaiter>();\n\t#nextId = 1;\n\t#pending = new Map<number, PendingRequest>();\n\treadonly #socket: WebSocket;\n\n\tprivate constructor(socket: WebSocket) {\n\t\tthis.#socket = socket;\n\t\tsocket.addEventListener(\"message\", this.onMessage);\n\t\tsocket.addEventListener(\"close\", this.onClose);\n\t\tsocket.addEventListener(\"error\", this.onError);\n\t}\n\n\tstatic connect(url: string, options: CdpConnectOptions = {}) {\n\t\tconst timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\t\tconst WebSocketImplementation = options.webSocketConstructor ?? WebSocket;\n\t\toptions.signal?.throwIfAborted();\n\t\treturn new Promise<CdpClient>((resolve, reject) => {\n\t\t\tconst socket = new WebSocketImplementation(url);\n\t\t\tlet settled = false;\n\t\t\tconst settle = (callback: () => void) => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\tsocket.removeEventListener(\"open\", onOpen);\n\t\t\t\tsocket.removeEventListener(\"error\", onConnectError);\n\t\t\t\tcallback();\n\t\t\t};\n\t\t\tconst onOpen = () => settle(() => resolve(new CdpClient(socket)));\n\t\t\tconst onConnectError = () =>\n\t\t\t\tsettle(() => {\n\t\t\t\t\tsocket.close();\n\t\t\t\t\treject(new Error(`Failed to connect to Chrome DevTools WebSocket: ${url}`));\n\t\t\t\t});\n\t\t\tconst onAbort = () =>\n\t\t\t\tsettle(() => {\n\t\t\t\t\tsocket.close();\n\t\t\t\t\treject(options.signal?.reason ?? abortError(\"Chrome DevTools connection aborted\"));\n\t\t\t\t});\n\t\t\tconst timeout = setTimeout(\n\t\t\t\t() =>\n\t\t\t\t\tsettle(() => {\n\t\t\t\t\t\tsocket.close();\n\t\t\t\t\t\treject(new Error(`Timed out connecting to Chrome DevTools WebSocket: ${url}`));\n\t\t\t\t\t}),\n\t\t\t\ttimeoutMs,\n\t\t\t);\n\t\t\toptions.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\tsocket.addEventListener(\"open\", onOpen, { once: true });\n\t\t\tsocket.addEventListener(\"error\", onConnectError, { once: true });\n\t\t});\n\t}\n\n\tsend<T = unknown>(\n\t\tmethod: string,\n\t\tparams: Record<string, unknown> = {},\n\t\toptions: CdpOperationOptions = {},\n\t) {\n\t\tthis.throwIfClosed();\n\t\toptions.signal?.throwIfAborted();\n\t\tconst id = this.#nextId;\n\t\tthis.#nextId += 1;\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst onAbort = () => {\n\t\t\t\tthis.#pending.delete(id);\n\t\t\t\tcleanup();\n\t\t\t\treject(options.signal?.reason ?? abortError(`CDP command aborted: ${method}`));\n\t\t\t};\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tthis.#pending.delete(id);\n\t\t\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\treject(new Error(`Timed out waiting for CDP response: ${method}`));\n\t\t\t}, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n\t\t\tconst cleanup = () => {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t};\n\t\t\tthis.#pending.set(id, {\n\t\t\t\tcleanup,\n\t\t\t\treject,\n\t\t\t\tresolve: resolve as (value: unknown) => void,\n\t\t\t});\n\t\t\toptions.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\ttry {\n\t\t\t\tthis.#socket.send(JSON.stringify({ id, method, params }));\n\t\t\t} catch (error) {\n\t\t\t\tthis.#pending.delete(id);\n\t\t\t\tcleanup();\n\t\t\t\treject(error);\n\t\t\t}\n\t\t});\n\t}\n\n\twaitForEvent<T>(\n\t\tmethod: string,\n\t\tpredicate: (params: unknown) => params is T,\n\t\toptions: CdpOperationOptions = {},\n\t): Promise<T> {\n\t\tthis.throwIfClosed();\n\t\toptions.signal?.throwIfAborted();\n\t\tconst buffered = this.#eventBuffers.get(method) ?? [];\n\t\tfor (const [index, params] of buffered.entries()) {\n\t\t\tif (!predicate(params)) continue;\n\t\t\tbuffered.splice(index, 1);\n\t\t\tif (buffered.length === 0) this.#eventBuffers.delete(method);\n\t\t\treturn Promise.resolve(params);\n\t\t}\n\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst waiter = {} as EventWaiter<T>;\n\t\t\tconst onAbort = () => {\n\t\t\t\tthis.#eventWaiters.delete(waiter as EventWaiter);\n\t\t\t\tcleanup();\n\t\t\t\treject(options.signal?.reason ?? abortError(`CDP event wait aborted: ${method}`));\n\t\t\t};\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tthis.#eventWaiters.delete(waiter as EventWaiter);\n\t\t\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\treject(new Error(`Timed out waiting for CDP event: ${method}`));\n\t\t\t}, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n\t\t\tconst cleanup = () => {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t};\n\t\t\tObject.assign(waiter, { cleanup, method, predicate, reject, resolve });\n\t\t\tthis.#eventWaiters.add(waiter as EventWaiter);\n\t\t\toptions.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t});\n\t}\n\n\tclose(reason: unknown = new Error(\"Chrome DevTools WebSocket closed\")) {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tthis.#socket.removeEventListener(\"message\", this.onMessage);\n\t\tthis.#socket.removeEventListener(\"close\", this.onClose);\n\t\tthis.#socket.removeEventListener(\"error\", this.onError);\n\t\tthis.rejectAll(reason);\n\t\tthis.#eventBuffers.clear();\n\t\ttry {\n\t\t\tthis.#socket.close();\n\t\t} catch {\n\t\t\t// The transport is already unusable; pending work has still been rejected.\n\t\t}\n\t}\n\n\tprivate readonly onClose = () => {\n\t\tthis.close(new Error(\"Chrome DevTools WebSocket closed\"));\n\t};\n\n\tprivate readonly onError = () => {\n\t\tthis.close(new Error(\"Chrome DevTools WebSocket error\"));\n\t};\n\n\tprivate readonly onMessage = (event: MessageEvent) => {\n\t\tif (typeof event.data !== \"string\") {\n\t\t\tthis.close(new Error(\"Chrome DevTools WebSocket sent an unsupported binary message\"));\n\t\t\treturn;\n\t\t}\n\t\tif (\n\t\t\tevent.data.length > MAX_CDP_MESSAGE_BYTES ||\n\t\t\tBuffer.byteLength(event.data, \"utf8\") > MAX_CDP_MESSAGE_BYTES\n\t\t) {\n\t\t\tthis.close(new Error(\"Chrome DevTools WebSocket message exceeds the 8 MB limit\"));\n\t\t\treturn;\n\t\t}\n\t\tlet payload: unknown;\n\t\ttry {\n\t\t\tpayload = JSON.parse(event.data) as unknown;\n\t\t} catch {\n\t\t\tthis.close(new Error(\"Chrome DevTools WebSocket sent malformed JSON\"));\n\t\t\treturn;\n\t\t}\n\t\tif (!isRecord(payload)) {\n\t\t\tthis.close(new Error(\"Chrome DevTools WebSocket sent a malformed message\"));\n\t\t\treturn;\n\t\t}\n\t\tif (typeof payload.id === \"number\") {\n\t\t\tthis.handleResponse(payload as unknown as CdpResponse);\n\t\t\treturn;\n\t\t}\n\t\tif (typeof payload.method !== \"string\") {\n\t\t\tthis.close(new Error(\"Chrome DevTools WebSocket sent a malformed event\"));\n\t\t\treturn;\n\t\t}\n\t\tthis.handleEvent(payload as unknown as CdpEvent);\n\t};\n\n\tprivate handleResponse(response: CdpResponse) {\n\t\tconst pending = this.#pending.get(response.id);\n\t\tif (!pending) return;\n\t\tthis.#pending.delete(response.id);\n\t\tpending.cleanup();\n\t\tif (response.error) {\n\t\t\tpending.reject(\n\t\t\t\tnew Error(\n\t\t\t\t\t`CDP error ${response.error.code}: ${response.error.message}${\n\t\t\t\t\t\tresponse.error.data === undefined ? \"\" : ` (${safeJson(response.error.data)})`\n\t\t\t\t\t}`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tpending.resolve(response.result);\n\t}\n\n\tprivate handleEvent(event: CdpEvent) {\n\t\tif (event.method === \"Inspector.detached\" || event.method === \"Target.detachedFromTarget\") {\n\t\t\tthis.close(new Error(`Chrome DevTools target detached: ${safeJson(event.params)}`));\n\t\t\treturn;\n\t\t}\n\t\tfor (const waiter of this.#eventWaiters) {\n\t\t\tif (waiter.method !== event.method) continue;\n\t\t\tlet matched: boolean;\n\t\t\ttry {\n\t\t\t\tmatched = waiter.predicate(event.params);\n\t\t\t} catch (error) {\n\t\t\t\tthis.#eventWaiters.delete(waiter);\n\t\t\t\twaiter.cleanup();\n\t\t\t\twaiter.reject(error);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!matched) continue;\n\t\t\tthis.#eventWaiters.delete(waiter);\n\t\t\twaiter.cleanup();\n\t\t\twaiter.resolve(event.params);\n\t\t\treturn;\n\t\t}\n\t\tconst buffer = this.#eventBuffers.get(event.method) ?? [];\n\t\tbuffer.push(event.params);\n\t\tif (buffer.length > MAX_BUFFERED_EVENTS_PER_METHOD) {\n\t\t\tthis.close(\n\t\t\t\tnew Error(\n\t\t\t\t\t`Chrome DevTools WebSocket buffered more than ${MAX_BUFFERED_EVENTS_PER_METHOD} ${event.method} events`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tthis.#eventBuffers.set(event.method, buffer);\n\t}\n\n\tprivate rejectAll(reason: unknown) {\n\t\tfor (const [id, pending] of this.#pending) {\n\t\t\tthis.#pending.delete(id);\n\t\t\tpending.cleanup();\n\t\t\tpending.reject(reason);\n\t\t}\n\t\tfor (const waiter of this.#eventWaiters) {\n\t\t\tthis.#eventWaiters.delete(waiter);\n\t\t\twaiter.cleanup();\n\t\t\twaiter.reject(reason);\n\t\t}\n\t}\n\n\tprivate throwIfClosed() {\n\t\tif (this.#closed) throw new Error(\"Chrome DevTools WebSocket is closed\");\n\t}\n}\n\nfunction abortError(message: string) {\n\treturn new DOMException(message, \"AbortError\");\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction safeJson(value: unknown) {\n\ttry {\n\t\treturn JSON.stringify(value);\n\t} catch {\n\t\treturn String(value);\n\t}\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -5,6 +5,7 @@ import {
5
5
  CORE_CHROME_DEVTOOLS_TOOL_NAMES,
6
6
  browserCandidateHint,
7
7
  browserLifecycleState,
8
+ browserSettingsForOwner,
8
9
  devToolsEndpoint,
9
10
  endpointConfigHint,
10
11
  endpointSourceLabel,
@@ -19,7 +20,7 @@ import {
19
20
  settingsFilePath,
20
21
  state,
21
22
  webMcpEnabled
22
- } from "./chunk-GVBXT3FB.js";
23
+ } from "./chunk-SRT3UUIP.js";
23
24
 
24
25
  // src/lazy-tools.ts
25
26
  import {
@@ -191,8 +192,37 @@ function unique(values) {
191
192
  return [...new Set(values)];
192
193
  }
193
194
 
195
+ // src/display.ts
196
+ var MAX_SANITIZER_INPUT_CODE_UNITS = 5e4;
197
+ var graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
198
+ function sanitizeChromeDevtoolsDisplay(value, maxCharacters = 5e4) {
199
+ const inputWasTruncated = value.length > MAX_SANITIZER_INPUT_CODE_UNITS;
200
+ const boundedInput = inputWasTruncated ? truncateAtGraphemeBoundary(value, MAX_SANITIZER_INPUT_CODE_UNITS) : value;
201
+ const normalizedLineEndings = boundedInput.replace(/\r\n/g, "\n");
202
+ const sanitized = Array.from(normalizedLineEndings, (character) => {
203
+ const codePoint = character.codePointAt(0) ?? 0;
204
+ const unsafeControl = codePoint >= 0 && codePoint <= 8 || codePoint >= 11 && codePoint <= 31 || codePoint >= 127 && codePoint <= 159;
205
+ const unsafeBidi = codePoint >= 8234 && codePoint <= 8238 || codePoint >= 8294 && codePoint <= 8297;
206
+ const loneSurrogate = character.length === 1 && codePoint >= 55296 && codePoint <= 57343;
207
+ return unsafeControl || unsafeBidi || loneSurrogate ? "\uFFFD" : character;
208
+ }).join("");
209
+ const outputLimit = Math.min(maxCharacters, MAX_SANITIZER_INPUT_CODE_UNITS);
210
+ if (!inputWasTruncated && sanitized.length <= outputLimit) return sanitized;
211
+ return `${truncateAtGraphemeBoundary(sanitized, Math.max(0, outputLimit - 1))}\u2026`;
212
+ }
213
+ function truncateAtGraphemeBoundary(value, maxCodeUnits) {
214
+ if (value.length <= maxCodeUnits) return value;
215
+ const boundedLookahead = value.slice(0, Math.max(0, maxCodeUnits) + 2);
216
+ let safeEnd = 0;
217
+ for (const { index, segment } of graphemeSegmenter.segment(boundedLookahead)) {
218
+ const segmentEnd = index + segment.length;
219
+ if (segmentEnd > maxCodeUnits) break;
220
+ safeEnd = segmentEnd;
221
+ }
222
+ return value.slice(0, safeEnd);
223
+ }
224
+
194
225
  // src/tool-selector.ts
195
- import { stripVTControlCharacters } from "node:util";
196
226
  function unique2(values) {
197
227
  return Array.from(new Set(values));
198
228
  }
@@ -319,7 +349,7 @@ async function buildToolStatusMessage(pi, owner) {
319
349
  ...state.settingsNotice ? [`Settings note: ${state.settingsNotice}`] : [],
320
350
  `Other active tools preserved: ${summary.activeNonChromeToolCount}`,
321
351
  `Endpoint: ${devToolsEndpoint(owner)}`,
322
- `Endpoint source: ${endpointSourceLabel()}`,
352
+ `Endpoint source: ${endpointSourceLabel(owner)}`,
323
353
  `Launch mode: ${launchModeLabel(owner)}`,
324
354
  ...launchAttemptLines(owner)
325
355
  ].join("\n")
@@ -329,6 +359,7 @@ function buildQuickstartMessage(owner) {
329
359
  return buildSettingsSetupMessage(owner);
330
360
  }
331
361
  function buildBrowserStatusMessage(owner) {
362
+ const browser = browserSettingsForOwner(owner);
332
363
  const lifecycle = browserLifecycleState(owner);
333
364
  const webMcpIsEnabled = owner ? webMcpEnabled(owner) : false;
334
365
  const browserState = lifecycle === "starting" ? "starting managed browser" : lifecycle === "running" ? "managed browser running" : lifecycle === "exited" ? "managed browser exited" : lifecycle === "failed" ? "last launch failed" : "not started; connection has not been checked";
@@ -338,16 +369,16 @@ function buildBrowserStatusMessage(owner) {
338
369
  `Browser: ${browserState}`,
339
370
  "Viewing this status does not probe the endpoint or launch Chrome.",
340
371
  `Endpoint: ${devToolsEndpoint(owner)}`,
341
- `Endpoint source: ${endpointSourceLabel()}`,
372
+ `Endpoint source: ${endpointSourceLabel(owner)}`,
342
373
  `Launch mode: ${launchModeLabel(owner)}`,
343
- `Unpacked extensions: ${state.extensionPaths.length} (${state.extensionPathsSource})`,
374
+ `Unpacked extensions: ${browser.extensionPaths.length} (${browser.extensionPathsSource})`,
344
375
  `WebMCP: ${webMcpIsEnabled ? "enabled \xB7 experimental" : "disabled \xB7 experimental"}`,
345
376
  ...webMcpIsEnabled && !managedBrowserForOwner(owner)?.ready ? [
346
377
  "WebMCP warning: attached browser profiles may contain everyday authenticated sessions and sensitive state."
347
378
  ] : [],
348
- ...state.extensionPaths.length > 0 ? ["Unpacked extensions execute trusted browser code in an isolated managed browser."] : [],
379
+ ...browser.extensionPaths.length > 0 ? ["Unpacked extensions execute trusted browser code in an isolated managed browser."] : [],
349
380
  ...launchAttemptLines(owner),
350
- ...needsRecovery ? [launchHint(), endpointConfigHint()] : []
381
+ ...needsRecovery ? [launchHint(owner), endpointConfigHint()] : []
351
382
  ].join("\n")
352
383
  );
353
384
  }
@@ -355,43 +386,32 @@ function buildSettingsSetupMessage(owner) {
355
386
  return sanitizeChromeDevtoolsDisplay(
356
387
  [
357
388
  `Chrome DevTools endpoint: ${devToolsEndpoint(owner)}`,
358
- `Endpoint source: ${endpointSourceLabel()}`,
389
+ `Endpoint source: ${endpointSourceLabel(owner)}`,
359
390
  `Launch mode: ${launchModeLabel(owner)}`,
360
391
  ...browserSettingsStatusLines(owner),
361
- launchHint(),
362
- browserCandidateHint(),
392
+ launchHint(owner),
393
+ browserCandidateHint(owner),
363
394
  ...launchAttemptLines(owner),
364
395
  endpointConfigHint()
365
396
  ].join("\n")
366
397
  );
367
398
  }
368
- function sanitizeChromeDevtoolsDisplay(value, maxCharacters = 5e4) {
369
- const withoutBidi = stripVTControlCharacters(value).replace(
370
- /[\u202a-\u202e\u2066-\u2069]/gu,
371
- "\uFFFD"
372
- );
373
- const sanitized = Array.from(withoutBidi, (character) => {
374
- const codePoint = character.codePointAt(0) ?? 0;
375
- const unsafeControl = codePoint >= 0 && codePoint <= 8 || codePoint >= 11 && codePoint <= 31 || codePoint >= 127 && codePoint <= 159;
376
- return unsafeControl ? "\uFFFD" : character;
377
- }).join("");
378
- if (sanitized.length <= maxCharacters) return sanitized;
379
- return `${sanitized.slice(0, Math.max(0, maxCharacters - 1))}\u2026`;
380
- }
381
399
  function browserSettingsStatusLines(owner) {
382
- const extensionLines = state.extensionPaths.length > 0 ? state.extensionPaths.map((extensionPath) => ` - ${extensionPath}`) : [" - none"];
400
+ const browser = browserSettingsForOwner(owner);
401
+ const extensionPaths = browser.extensionPaths;
402
+ const extensionLines = extensionPaths.length > 0 ? extensionPaths.map((extensionPath) => ` - ${extensionPath}`) : [" - none"];
383
403
  return [
384
404
  `Settings file: ${state.settingsFilePath ?? settingsFilePath()} (user)`,
385
405
  ...state.projectSettingsFilePath ? [
386
406
  `Project settings: ${state.projectSettingsFilePath} (${state.projectSettingsTrusted ? "trusted" : "untrusted; ignored"})`
387
407
  ] : [],
388
- `Auto-launch: ${state.autoLaunchEnabled ? "on" : "off"} (${state.autoLaunchSource})`,
389
- `Browser executable: ${state.browserExecutable ?? "automatic discovery"} (${state.browserExecutableSource})`,
390
- `Unpacked extensions (${state.extensionPathsSource}):`,
408
+ `Auto-launch: ${browser.autoLaunchEnabled ? "on" : "off"} (${browser.autoLaunchSource})`,
409
+ `Browser executable: ${browser.executablePath ?? "automatic discovery"} (${browser.executablePathSource})`,
410
+ `Unpacked extensions (${browser.extensionPathsSource}):`,
391
411
  ...extensionLines,
392
412
  `WebMCP: ${webMcpEnabled(owner) ? "enabled \xB7 experimental \xB7 every call requires confirmation" : "disabled \xB7 experimental"}`,
393
413
  "Confirmed menu settings apply before the next browser connection; manual JSON edits require /reload or session replacement.",
394
- ...state.extensionPaths.length > 0 ? [
414
+ ...extensionPaths.length > 0 ? [
395
415
  "Unpacked extensions require Chrome for Testing or Chromium and execute trusted browser code."
396
416
  ] : []
397
417
  ];
@@ -452,14 +472,14 @@ export {
452
472
  availableChromeDevtoolsTools,
453
473
  configuredChromeDevtoolsTools,
454
474
  createChromeDevtoolsLoadTool,
475
+ sanitizeChromeDevtoolsDisplay,
455
476
  updateChromeDevtoolsTools,
456
477
  setSelectedChromeDevtoolsTools,
457
478
  waitForChromeDevtoolsSettings,
458
479
  buildToolStatusMessage,
459
480
  buildQuickstartMessage,
460
481
  buildBrowserStatusMessage,
461
- sanitizeChromeDevtoolsDisplay,
462
482
  buildCommandGuide,
463
483
  allChromeDevtoolsTools
464
484
  };
465
- //# sourceMappingURL=chunk-B7B63PWB.js.map
485
+ //# sourceMappingURL=chunk-LLXOCRNF.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lazy-tools.ts", "../../src/display.ts", "../../src/tool-selector.ts"],
4
+ "sourcesContent": ["import {\n\tdefineTool,\n\ttype ExtensionAPI,\n\ttype ExtensionContext,\n} from \"@earendil-works/pi-coding-agent\";\nimport { Type } from \"typebox\";\nimport { webMcpEnabled } from \"./runtime.js\";\nimport {\n\tCHROME_DEVTOOLS_TOOL_NAMES,\n\ttype ChromeDevToolsToolName,\n\tisWebMcpToolName,\n} from \"./tool-names.js\";\n\nexport const CHROME_DEVTOOLS_LOAD_TOOL_NAME = \"chrome_devtools_load\";\n\nconst AVAILABLE_TOOLS_STORE = Symbol.for(\"@narumitw/pi-chrome-devtools.available-tools-store\");\ntype ChromeDevtoolsGlobal = typeof globalThis & {\n\t[AVAILABLE_TOOLS_STORE]?: WeakMap<ExtensionAPI, Set<ChromeDevToolsToolName>>;\n};\nconst sharedGlobal = globalThis as ChromeDevtoolsGlobal;\nconst existingAvailableToolsStore = sharedGlobal[AVAILABLE_TOOLS_STORE];\nconst availableToolsByApi =\n\texistingAvailableToolsStore ?? new WeakMap<ExtensionAPI, Set<ChromeDevToolsToolName>>();\nif (!existingAvailableToolsStore) sharedGlobal[AVAILABLE_TOOLS_STORE] = availableToolsByApi;\nconst lazyExposureByApi = new WeakMap<ExtensionAPI, boolean>();\nconst sessionOwnerByApi = new WeakMap<ExtensionAPI, object>();\n\nconst SEARCH_TEXT: Record<ChromeDevToolsToolName, string> = {\n\tchrome_devtools_list_pages: \"list open inspectable chrome browser pages tabs targets\",\n\tchrome_devtools_select_page: \"select choose active chrome browser page tab target\",\n\tchrome_devtools_navigate: \"navigate open create chrome browser page url website\",\n\tchrome_devtools_evaluate: \"evaluate run javascript expression dom inspect chrome browser page\",\n\tchrome_devtools_screenshot: \"capture screenshot png image visual chrome browser page\",\n\tchrome_devtools_webmcp_list_tools:\n\t\t\"list discover page provided website webmcp tools capabilities experimental\",\n\tchrome_devtools_webmcp_call_tool:\n\t\t\"call invoke page provided website webmcp tool confirmation experimental\",\n};\n\nexport function setChromeDevtoolsSessionOwner(pi: ExtensionAPI, owner: object) {\n\tsessionOwnerByApi.set(pi, owner);\n}\n\nexport function initializeAvailableChromeDevtoolsTools(pi: ExtensionAPI) {\n\tif (availableToolsByApi.has(pi)) return;\n\tconst activeTools = new Set(pi.getActiveTools());\n\tsetAvailableTools(\n\t\tpi,\n\t\tCHROME_DEVTOOLS_TOOL_NAMES.filter((name) => activeTools.has(name)),\n\t);\n}\n\nexport function configureChromeDevtoolsToolExposure(\n\tpi: ExtensionAPI,\n\tavailableTools: readonly ChromeDevToolsToolName[],\n\tmodel?: ExtensionContext[\"model\"],\n) {\n\tsetAvailableTools(pi, availableTools);\n\tconst available = effectiveAvailableTools(pi);\n\tconst lazyExposure = supportsNativeDeferredToolLoading(model);\n\tlazyExposureByApi.set(pi, lazyExposure);\n\tconst exposedTools = lazyExposure\n\t\t? []\n\t\t: CHROME_DEVTOOLS_TOOL_NAMES.filter((name) => available.has(name));\n\tconst nonCapabilityTools = pi\n\t\t.getActiveTools()\n\t\t.filter((name) => !CHROME_DEVTOOLS_TOOL_NAMES.includes(name as ChromeDevToolsToolName));\n\tpi.setActiveTools(\n\t\tunique([...nonCapabilityTools, CHROME_DEVTOOLS_LOAD_TOOL_NAME, ...exposedTools]),\n\t);\n}\n\nexport function requireEagerChromeDevtoolsToolExposure(pi: ExtensionAPI) {\n\tlazyExposureByApi.set(pi, false);\n\tconst active = pi.getActiveTools();\n\tconst available = availableChromeDevtoolsTools(pi);\n\tpi.setActiveTools(unique([...active, CHROME_DEVTOOLS_LOAD_TOOL_NAME, ...available]));\n}\n\nexport function applyAvailableChromeDevtoolsTools(\n\tpi: ExtensionAPI,\n\tavailableTools: readonly ChromeDevToolsToolName[],\n) {\n\tsetAvailableTools(pi, availableTools);\n\tconst available = effectiveAvailableTools(pi);\n\tconst lazyExposure = lazyExposureByApi.get(pi) === true;\n\tconst active = pi\n\t\t.getActiveTools()\n\t\t.filter(\n\t\t\t(name) =>\n\t\t\t\t!CHROME_DEVTOOLS_TOOL_NAMES.includes(name as ChromeDevToolsToolName) ||\n\t\t\t\t(lazyExposure && available.has(name as ChromeDevToolsToolName)),\n\t\t);\n\tconst eagerTools = lazyExposure\n\t\t? []\n\t\t: CHROME_DEVTOOLS_TOOL_NAMES.filter((name) => available.has(name));\n\tpi.setActiveTools(unique([...active, CHROME_DEVTOOLS_LOAD_TOOL_NAME, ...eagerTools]));\n}\n\nexport function chromeDevtoolsToolExposureMode(pi: ExtensionAPI) {\n\treturn lazyExposureByApi.get(pi) === true ? \"native deferred\" : \"eager\";\n}\n\nexport function supportsNativeDeferredToolLoading(model: ExtensionContext[\"model\"]): boolean {\n\tif (!model) return false;\n\tif (model.api === \"anthropic-messages\") {\n\t\tconst configured = compatBoolean(model.compat, \"supportsToolReferences\");\n\t\tif (configured !== undefined) return configured;\n\t\tif (model.provider !== \"anthropic\" || model.id.includes(\"haiku\")) return false;\n\t\tconst version = model.id.match(/^claude-(?:opus|sonnet|fable)-(\\d+)(?:-(\\d+))?(?:-|$)/);\n\t\tif (!version) return false;\n\t\tconst major = Number(version[1]);\n\t\tconst minor = version[2] && version[2].length < 8 ? Number(version[2]) : 0;\n\t\treturn major > 4 || (major === 4 && minor >= 5);\n\t}\n\tif (model.api === \"openai-completions\") {\n\t\treturn compatString(model.compat, \"deferredToolsMode\") === \"kimi\";\n\t}\n\tif (model.api === \"openai-responses\" || model.api === \"openai-codex-responses\") {\n\t\treturn (\n\t\t\tcompatBoolean(model.compat, \"supportsAdditionalTools\") === true ||\n\t\t\tcompatBoolean(model.compat, \"supportsToolSearch\") === true\n\t\t);\n\t}\n\treturn false;\n}\n\nexport function availableChromeDevtoolsTools(pi: ExtensionAPI) {\n\tconst available = effectiveAvailableTools(pi);\n\treturn CHROME_DEVTOOLS_TOOL_NAMES.filter((name) => available.has(name));\n}\n\nexport function configuredChromeDevtoolsTools(pi: ExtensionAPI) {\n\tconst available = availableToolsByApi.get(pi) ?? new Set();\n\treturn CHROME_DEVTOOLS_TOOL_NAMES.filter((name) => available.has(name));\n}\n\nexport function createChromeDevtoolsLoadTool(pi: ExtensionAPI) {\n\treturn defineTool({\n\t\tname: CHROME_DEVTOOLS_LOAD_TOOL_NAME,\n\t\tlabel: \"Chrome DevTools: Load Tools\",\n\t\tdescription:\n\t\t\t\"Find and enable Chrome DevTools browser tools relevant to a task. Loaded tools remain available for the session.\",\n\t\tpromptSnippet: \"Load Chrome DevTools browser capabilities on demand\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use chrome_devtools_load when a task requires inspecting or controlling a Chrome browser and the needed chrome_devtools_* capability is not active.\",\n\t\t],\n\t\tparameters: Type.Object({\n\t\t\tquery: Type.String({\n\t\t\t\tdescription: \"Browser capability or task to find tools for.\",\n\t\t\t\tmaxLength: 500,\n\t\t\t}),\n\t\t\tlimit: Type.Optional(\n\t\t\t\tType.Integer({\n\t\t\t\t\tdescription: \"Maximum tools to load. Defaults to 3.\",\n\t\t\t\t\tminimum: 1,\n\t\t\t\t\tmaximum: 5,\n\t\t\t\t}),\n\t\t\t),\n\t\t}),\n\t\tasync execute(_toolCallId, params, signal, _onUpdate, ctx) {\n\t\t\tsignal?.throwIfAborted();\n\t\t\tsetChromeDevtoolsSessionOwner(pi, ctx.sessionManager);\n\t\t\tconst available = new Set(availableChromeDevtoolsTools(pi));\n\t\t\tconst matches = matchChromeDevtoolsTools(params.query, params.limit ?? 3, available);\n\t\t\tconst active = pi.getActiveTools();\n\t\t\tconst activeSet = new Set(active);\n\t\t\tconst added = matches.filter((name) => !activeSet.has(name));\n\t\t\tif (added.length > 0) {\n\t\t\t\tpi.setActiveTools(unique([...active, ...added]));\n\t\t\t}\n\n\t\t\tconst text =\n\t\t\t\tmatches.length === 0\n\t\t\t\t\t? \"No available Chrome DevTools tools matched the query.\"\n\t\t\t\t\t: added.length > 0\n\t\t\t\t\t\t? `Loaded Chrome DevTools tools: ${added.join(\", \")}`\n\t\t\t\t\t\t: `Matching Chrome DevTools tools are already loaded: ${matches.join(\", \")}`;\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text }],\n\t\t\t\tdetails: { matches, added },\n\t\t\t};\n\t\t},\n\t});\n}\n\nfunction matchChromeDevtoolsTools(\n\tquery: string,\n\tlimit: number,\n\tavailable: ReadonlySet<ChromeDevToolsToolName>,\n) {\n\tconst terms = query\n\t\t.toLowerCase()\n\t\t.split(/[^a-z0-9]+/)\n\t\t.filter((term) => term.length >= 2);\n\tif (terms.length === 0) return [];\n\treturn CHROME_DEVTOOLS_TOOL_NAMES.filter((name) => available.has(name))\n\t\t.map((name, index) => ({\n\t\t\tname,\n\t\t\tindex,\n\t\t\tscore: terms.reduce((score, term) => score + (SEARCH_TEXT[name].includes(term) ? 1 : 0), 0),\n\t\t}))\n\t\t.filter((match) => match.score > 0)\n\t\t.sort((left, right) => right.score - left.score || left.index - right.index)\n\t\t.slice(0, limit)\n\t\t.map((match) => match.name);\n}\n\nfunction setAvailableTools(pi: ExtensionAPI, availableTools: readonly ChromeDevToolsToolName[]) {\n\tconst available = new Set(availableTools);\n\tavailableToolsByApi.set(pi, available);\n\treturn available;\n}\n\nfunction effectiveAvailableTools(pi: ExtensionAPI) {\n\tconst configured = availableToolsByApi.get(pi) ?? new Set();\n\tconst owner = sessionOwnerByApi.get(pi);\n\tconst enabled = owner !== undefined && webMcpEnabled(owner);\n\treturn new Set(\n\t\tCHROME_DEVTOOLS_TOOL_NAMES.filter(\n\t\t\t(name) => configured.has(name) && (enabled || !isWebMcpToolName(name)),\n\t\t),\n\t);\n}\n\nfunction compatBoolean(value: unknown, key: string) {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined;\n\tconst record = value as Record<string, unknown>;\n\treturn typeof record[key] === \"boolean\" ? record[key] : undefined;\n}\n\nfunction compatString(value: unknown, key: string) {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined;\n\tconst record = value as Record<string, unknown>;\n\treturn typeof record[key] === \"string\" ? record[key] : undefined;\n}\n\nfunction unique(values: readonly string[]) {\n\treturn [...new Set(values)];\n}\n", "const MAX_SANITIZER_INPUT_CODE_UNITS = 50_000;\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nexport function sanitizeChromeDevtoolsDisplay(value: string, maxCharacters = 50_000) {\n\tconst inputWasTruncated = value.length > MAX_SANITIZER_INPUT_CODE_UNITS;\n\tconst boundedInput = inputWasTruncated\n\t\t? truncateAtGraphemeBoundary(value, MAX_SANITIZER_INPUT_CODE_UNITS)\n\t\t: value;\n\tconst normalizedLineEndings = boundedInput.replace(/\\r\\n/g, \"\\n\");\n\t// Neutralize controls without parsing untrusted terminal sequences; keep printable payload visible.\n\tconst sanitized = Array.from(normalizedLineEndings, (character) => {\n\t\tconst codePoint = character.codePointAt(0) ?? 0;\n\t\tconst unsafeControl =\n\t\t\t(codePoint >= 0 && codePoint <= 8) ||\n\t\t\t(codePoint >= 11 && codePoint <= 31) ||\n\t\t\t(codePoint >= 127 && codePoint <= 159);\n\t\tconst unsafeBidi =\n\t\t\t(codePoint >= 0x202a && codePoint <= 0x202e) || (codePoint >= 0x2066 && codePoint <= 0x2069);\n\t\tconst loneSurrogate = character.length === 1 && codePoint >= 0xd800 && codePoint <= 0xdfff;\n\t\treturn unsafeControl || unsafeBidi || loneSurrogate ? \"\uFFFD\" : character;\n\t}).join(\"\");\n\tconst outputLimit = Math.min(maxCharacters, MAX_SANITIZER_INPUT_CODE_UNITS);\n\tif (!inputWasTruncated && sanitized.length <= outputLimit) return sanitized;\n\n\treturn `${truncateAtGraphemeBoundary(sanitized, Math.max(0, outputLimit - 1))}\u2026`;\n}\n\nfunction truncateAtGraphemeBoundary(value: string, maxCodeUnits: number) {\n\tif (value.length <= maxCodeUnits) return value;\n\tconst boundedLookahead = value.slice(0, Math.max(0, maxCodeUnits) + 2);\n\tlet safeEnd = 0;\n\tfor (const { index, segment } of graphemeSegmenter.segment(boundedLookahead)) {\n\t\tconst segmentEnd = index + segment.length;\n\t\tif (segmentEnd > maxCodeUnits) break;\n\t\tsafeEnd = segmentEnd;\n\t}\n\treturn value.slice(0, safeEnd);\n}\n", "import type { ExtensionAPI, ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport {\n\tbrowserCandidateHint,\n\tbrowserLifecycleState,\n\tbrowserSettingsForOwner,\n\tdevToolsEndpoint,\n\tendpointConfigHint,\n\tendpointSourceLabel,\n\tlaunchAttemptLines,\n\tlaunchHint,\n\tlaunchModeLabel,\n\tmanagedBrowserForOwner,\n} from \"./browser-manager.js\";\nimport { sanitizeChromeDevtoolsDisplay } from \"./display.js\";\nimport {\n\tapplyAvailableChromeDevtoolsTools,\n\tavailableChromeDevtoolsTools,\n\tCHROME_DEVTOOLS_LOAD_TOOL_NAME,\n\tchromeDevtoolsToolExposureMode,\n} from \"./lazy-tools.js\";\nimport { invalidateWebMcpOperations, state, webMcpEnabled } from \"./runtime.js\";\nimport { loadSettings, saveSettings, settingsFilePath } from \"./settings.js\";\nimport {\n\tCHROME_DEVTOOLS_TOOL_NAMES,\n\ttype ChromeDevToolsToolName,\n\tCORE_CHROME_DEVTOOLS_TOOL_NAMES,\n\tisWebMcpToolName,\n} from \"./tool-names.js\";\n\nexport { sanitizeChromeDevtoolsDisplay };\n\ntype CommandContext = ExtensionCommandContext;\n\nfunction unique<T>(values: T[]) {\n\treturn Array.from(new Set(values));\n}\n\nfunction formatError(error: unknown) {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\ninterface ToolStatusSummary {\n\tavailabilityStatus: \"enabled\" | \"disabled\" | \"partial\";\n\tavailableChromeToolCount: number;\n\tloadedChromeToolCount: number;\n\tactiveNonChromeToolCount: number;\n\tcapabilityCount: number;\n}\n\ntype ToolSelectionSaveResult = \"saved\" | \"active-tools-changed\" | \"failed\";\n\nexport async function updateChromeDevtoolsTools(\n\tpi: ExtensionAPI,\n\tctx: CommandContext,\n\tselectedTools: readonly ChromeDevToolsToolName[],\n\taction: string,\n) {\n\tconst generation = state.sessionGeneration;\n\tconst result = await transactSelectedTools(pi, ctx, selectedTools, generation);\n\tif (result !== \"saved\" || generation !== state.sessionGeneration) return;\n\tconst status = await buildToolStatusMessage(pi, ctx.sessionManager);\n\tif (generation !== state.sessionGeneration) return;\n\tctx.ui.notify(`Chrome DevTools tool catalog ${action}.\\n\\n${status}`, \"info\");\n}\n\nexport async function setSelectedChromeDevtoolsTools(\n\tpi: ExtensionAPI,\n\tctx: CommandContext,\n\tselectedTools: readonly ChromeDevToolsToolName[],\n\texpectedActiveTools: readonly ChromeDevToolsToolName[],\n): Promise<ToolSelectionSaveResult> {\n\treturn transactSelectedTools(\n\t\tpi,\n\t\tctx,\n\t\tselectedTools,\n\t\tstate.sessionGeneration,\n\t\texpectedActiveTools,\n\t);\n}\n\nlet toolTransactionQueue = Promise.resolve();\n\nexport async function waitForChromeDevtoolsSettings(): Promise<void> {\n\tawait toolTransactionQueue;\n}\n\nfunction transactSelectedTools(\n\tpi: ExtensionAPI,\n\tctx: CommandContext,\n\tselectedTools: readonly ChromeDevToolsToolName[],\n\texpectedGeneration: number,\n\texpectedActiveTools?: readonly ChromeDevToolsToolName[],\n): Promise<ToolSelectionSaveResult> {\n\tconst operation = toolTransactionQueue.then(() =>\n\t\ttransactSelectedToolsNow(pi, ctx, selectedTools, expectedGeneration, expectedActiveTools),\n\t);\n\ttoolTransactionQueue = operation.then(\n\t\t() => undefined,\n\t\t() => undefined,\n\t);\n\treturn operation;\n}\n\nasync function transactSelectedToolsNow(\n\tpi: ExtensionAPI,\n\tctx: CommandContext,\n\tselectedTools: readonly ChromeDevToolsToolName[],\n\texpectedGeneration: number,\n\texpectedActiveTools?: readonly ChromeDevToolsToolName[],\n): Promise<ToolSelectionSaveResult> {\n\tif (expectedGeneration !== state.sessionGeneration) return \"failed\";\n\tif (expectedActiveTools && !arraysEqual(availableChromeDevtoolsTools(pi), expectedActiveTools)) {\n\t\tctx.ui.notify(\n\t\t\t\"Browser tool selection changed while review was open. Review the current state, then apply again.\",\n\t\t\t\"warning\",\n\t\t);\n\t\treturn \"active-tools-changed\";\n\t}\n\tconst previousActiveTools = pi.getActiveTools();\n\tconst previousAvailableTools = availableChromeDevtoolsTools(pi);\n\ttry {\n\t\tconst previousWebMcpTools = previousAvailableTools.filter(isWebMcpToolName);\n\t\tconst selectedWebMcpTools = selectedTools.filter(isWebMcpToolName);\n\t\tif (!arraysEqual(previousWebMcpTools, selectedWebMcpTools)) {\n\t\t\tinvalidateWebMcpOperations(\n\t\t\t\tctx.sessionManager,\n\t\t\t\t\"Chrome DevTools WebMCP gateway availability changed\",\n\t\t\t);\n\t\t}\n\t\tapplyChromeDevtoolsTools(pi, selectedTools);\n\t\tawait persistSettings(selectedTools);\n\t\treturn expectedGeneration === state.sessionGeneration ? \"saved\" : \"failed\";\n\t} catch (error) {\n\t\tlet rollbackError: unknown;\n\t\ttry {\n\t\t\tapplyAvailableChromeDevtoolsTools(pi, previousAvailableTools);\n\t\t\tconst currentNonChromeTools = pi\n\t\t\t\t.getActiveTools()\n\t\t\t\t.filter((name) => !CHROME_DEVTOOLS_TOOL_NAMES.includes(name as ChromeDevToolsToolName));\n\t\t\tconst previousLoadedChromeTools = previousActiveTools.filter((name) =>\n\t\t\t\tCHROME_DEVTOOLS_TOOL_NAMES.includes(name as ChromeDevToolsToolName),\n\t\t\t);\n\t\t\tconst restoredChromeTools =\n\t\t\t\tchromeDevtoolsToolExposureMode(pi) === \"eager\"\n\t\t\t\t\t? previousAvailableTools\n\t\t\t\t\t: previousLoadedChromeTools;\n\t\t\tpi.setActiveTools(unique([...currentNonChromeTools, ...restoredChromeTools]));\n\t\t} catch (caught) {\n\t\t\trollbackError = caught;\n\t\t}\n\t\tif (expectedGeneration !== state.sessionGeneration) return \"failed\";\n\t\tctx.ui.notify(\n\t\t\tsanitizeChromeDevtoolsDisplay(\n\t\t\t\trollbackError\n\t\t\t\t\t? `Chrome DevTools settings save failed: ${formatError(error)}; active-tool rollback failed: ${formatError(rollbackError)}`\n\t\t\t\t\t: `Chrome DevTools settings save failed; active tools restored: ${formatError(error)}`,\n\t\t\t),\n\t\t\t\"warning\",\n\t\t);\n\t\treturn \"failed\";\n\t}\n}\n\nfunction arraysEqual<T>(left: readonly T[], right: readonly T[]) {\n\treturn left.length === right.length && left.every((value, index) => value === right[index]);\n}\n\nexport function applyChromeDevtoolsTools(\n\tpi: ExtensionAPI,\n\tselectedTools: readonly ChromeDevToolsToolName[],\n) {\n\tapplyAvailableChromeDevtoolsTools(pi, selectedTools);\n}\n\nfunction getToolStatusSummary(pi: ExtensionAPI, owner: object): ToolStatusSummary {\n\tconst chromeToolNames = new Set<string>(CHROME_DEVTOOLS_TOOL_NAMES);\n\tconst activeToolNames = new Set(pi.getActiveTools());\n\tconst loadedChromeToolCount = CHROME_DEVTOOLS_TOOL_NAMES.filter((name) =>\n\t\tactiveToolNames.has(name),\n\t).length;\n\tconst availableChromeToolCount = availableChromeDevtoolsTools(pi).length;\n\tconst activeNonChromeToolCount = Array.from(activeToolNames).filter(\n\t\t(name) => !chromeToolNames.has(name) && name !== CHROME_DEVTOOLS_LOAD_TOOL_NAME,\n\t).length;\n\tconst capabilityCount = effectiveCatalog(owner).length;\n\tconst availabilityStatus =\n\t\tavailableChromeToolCount === capabilityCount\n\t\t\t? \"enabled\"\n\t\t\t: availableChromeToolCount === 0\n\t\t\t\t? \"disabled\"\n\t\t\t\t: \"partial\";\n\n\treturn {\n\t\tavailabilityStatus,\n\t\tavailableChromeToolCount,\n\t\tloadedChromeToolCount,\n\t\tactiveNonChromeToolCount,\n\t\tcapabilityCount,\n\t};\n}\n\nexport async function buildToolStatusMessage(pi: ExtensionAPI, owner: object) {\n\tconst summary = getToolStatusSummary(pi, owner);\n\tconst persistedSetting = await persistedSettingLabel();\n\treturn sanitizeChromeDevtoolsDisplay(\n\t\t[\n\t\t\t`Chrome DevTools tools available: ${formatRuntimeStatus(summary)}`,\n\t\t\t`Tool exposure: ${chromeDevtoolsToolExposureMode(pi)}`,\n\t\t\t`Loaded capability tools this session: ${summary.loadedChromeToolCount}/${summary.capabilityCount}`,\n\t\t\t`WebMCP: ${webMcpEnabled(owner) ? \"enabled \u00B7 experimental \u00B7 confirmation required for every call\" : \"disabled \u00B7 experimental\"}`,\n\t\t\t`Loader: ${pi.getActiveTools().includes(CHROME_DEVTOOLS_LOAD_TOOL_NAME) ? \"active\" : \"inactive\"}`,\n\t\t\t`Persisted tool catalog: ${persistedSetting}`,\n\t\t\t...browserSettingsStatusLines(owner),\n\t\t\t...(state.settingsNotice ? [`Settings note: ${state.settingsNotice}`] : []),\n\t\t\t`Other active tools preserved: ${summary.activeNonChromeToolCount}`,\n\t\t\t`Endpoint: ${devToolsEndpoint(owner)}`,\n\t\t\t`Endpoint source: ${endpointSourceLabel(owner)}`,\n\t\t\t`Launch mode: ${launchModeLabel(owner)}`,\n\t\t\t...launchAttemptLines(owner),\n\t\t].join(\"\\n\"),\n\t);\n}\n\nexport function buildQuickstartMessage(owner: object) {\n\treturn buildSettingsSetupMessage(owner);\n}\n\nexport function buildBrowserStatusMessage(owner?: object) {\n\tconst browser = browserSettingsForOwner(owner);\n\tconst lifecycle = browserLifecycleState(owner);\n\tconst webMcpIsEnabled = owner ? webMcpEnabled(owner) : false;\n\tconst browserState =\n\t\tlifecycle === \"starting\"\n\t\t\t? \"starting managed browser\"\n\t\t\t: lifecycle === \"running\"\n\t\t\t\t? \"managed browser running\"\n\t\t\t\t: lifecycle === \"exited\"\n\t\t\t\t\t? \"managed browser exited\"\n\t\t\t\t\t: lifecycle === \"failed\"\n\t\t\t\t\t\t? \"last launch failed\"\n\t\t\t\t\t\t: \"not started; connection has not been checked\";\n\tconst needsRecovery = lifecycle === \"exited\" || lifecycle === \"failed\";\n\treturn sanitizeChromeDevtoolsDisplay(\n\t\t[\n\t\t\t`Browser: ${browserState}`,\n\t\t\t\"Viewing this status does not probe the endpoint or launch Chrome.\",\n\t\t\t`Endpoint: ${devToolsEndpoint(owner)}`,\n\t\t\t`Endpoint source: ${endpointSourceLabel(owner)}`,\n\t\t\t`Launch mode: ${launchModeLabel(owner)}`,\n\t\t\t`Unpacked extensions: ${browser.extensionPaths.length} (${browser.extensionPathsSource})`,\n\t\t\t`WebMCP: ${webMcpIsEnabled ? \"enabled \u00B7 experimental\" : \"disabled \u00B7 experimental\"}`,\n\t\t\t...(webMcpIsEnabled && !managedBrowserForOwner(owner)?.ready\n\t\t\t\t? [\n\t\t\t\t\t\t\"WebMCP warning: attached browser profiles may contain everyday authenticated sessions and sensitive state.\",\n\t\t\t\t\t]\n\t\t\t\t: []),\n\t\t\t...(browser.extensionPaths.length > 0\n\t\t\t\t? [\"Unpacked extensions execute trusted browser code in an isolated managed browser.\"]\n\t\t\t\t: []),\n\t\t\t...launchAttemptLines(owner),\n\t\t\t...(needsRecovery ? [launchHint(owner), endpointConfigHint()] : []),\n\t\t].join(\"\\n\"),\n\t);\n}\n\nexport function buildSettingsSetupMessage(owner: object) {\n\treturn sanitizeChromeDevtoolsDisplay(\n\t\t[\n\t\t\t`Chrome DevTools endpoint: ${devToolsEndpoint(owner)}`,\n\t\t\t`Endpoint source: ${endpointSourceLabel(owner)}`,\n\t\t\t`Launch mode: ${launchModeLabel(owner)}`,\n\t\t\t...browserSettingsStatusLines(owner),\n\t\t\tlaunchHint(owner),\n\t\t\tbrowserCandidateHint(owner),\n\t\t\t...launchAttemptLines(owner),\n\t\t\tendpointConfigHint(),\n\t\t].join(\"\\n\"),\n\t);\n}\n\nfunction browserSettingsStatusLines(owner: object) {\n\tconst browser = browserSettingsForOwner(owner);\n\tconst extensionPaths = browser.extensionPaths;\n\tconst extensionLines =\n\t\textensionPaths.length > 0\n\t\t\t? extensionPaths.map((extensionPath) => ` - ${extensionPath}`)\n\t\t\t: [\" - none\"];\n\treturn [\n\t\t`Settings file: ${state.settingsFilePath ?? settingsFilePath()} (user)`,\n\t\t...(state.projectSettingsFilePath\n\t\t\t? [\n\t\t\t\t\t`Project settings: ${state.projectSettingsFilePath} (${state.projectSettingsTrusted ? \"trusted\" : \"untrusted; ignored\"})`,\n\t\t\t\t]\n\t\t\t: []),\n\t\t`Auto-launch: ${browser.autoLaunchEnabled ? \"on\" : \"off\"} (${browser.autoLaunchSource})`,\n\t\t`Browser executable: ${browser.executablePath ?? \"automatic discovery\"} (${browser.executablePathSource})`,\n\t\t`Unpacked extensions (${browser.extensionPathsSource}):`,\n\t\t...extensionLines,\n\t\t`WebMCP: ${webMcpEnabled(owner) ? \"enabled \u00B7 experimental \u00B7 every call requires confirmation\" : \"disabled \u00B7 experimental\"}`,\n\t\t\"Confirmed menu settings apply before the next browser connection; manual JSON edits require /reload or session replacement.\",\n\t\t...(extensionPaths.length > 0\n\t\t\t? [\n\t\t\t\t\t\"Unpacked extensions require Chrome for Testing or Chromium and execute trusted browser code.\",\n\t\t\t\t]\n\t\t\t: []),\n\t];\n}\n\nexport function buildCommandGuide(owner: object) {\n\treturn [\n\t\t\"Chrome DevTools commands:\",\n\t\t`WebMCP: ${webMcpEnabled(owner) ? \"enabled\" : \"disabled\"} \u00B7 experimental \u00B7 every page-provided call requires confirmation`,\n\t\t\"/chrome-devtools \u2014 open this menu\",\n\t\t\"/chrome-devtools help \u2014 show command usage\",\n\t\t\"/chrome-devtools quickstart \u2014 show endpoint and launch help\",\n\t\t\"/chrome-devtools status \u2014 show tool and settings status\",\n\t\t\"/chrome-devtools settings \u2014 edit browser connection settings\",\n\t\t\"/chrome-devtools tools \u2014 choose available Chrome DevTools tools\",\n\t\t\"/chrome-devtools toggle|select \u2014 compatibility aliases for tools\",\n\t\t\"/chrome-devtools enable|on \u2014 make all Chrome DevTools tools available\",\n\t\t\"/chrome-devtools disable|off \u2014 make all Chrome DevTools capability tools unavailable\",\n\t].join(\"\\n\");\n}\n\nexport function allChromeDevtoolsTools(owner: object) {\n\treturn effectiveCatalog(owner);\n}\n\nexport function orderedChromeDevtoolsTools(selectedTools: ReadonlySet<ChromeDevToolsToolName>) {\n\treturn CHROME_DEVTOOLS_TOOL_NAMES.filter((toolName) => selectedTools.has(toolName));\n}\n\nfunction formatRuntimeStatus(summary: ToolStatusSummary) {\n\treturn `${summary.availabilityStatus} (${summary.availableChromeToolCount}/${summary.capabilityCount} available)`;\n}\n\nasync function persistedSettingLabel() {\n\tconst settings = await loadSettings();\n\tif (settings.kind === \"loaded\" && settings.settings.tools) {\n\t\treturn formatPersistedSelection(settings.settings.tools);\n\t}\n\tif (settings.kind === \"invalid\") {\n\t\treturn `none; current active-tool policy preserved (invalid settings ignored: ${settings.reason})`;\n\t}\n\treturn \"none; current active-tool policy preserved\";\n}\n\nfunction formatPersistedSelection(tools: readonly ChromeDevToolsToolName[]) {\n\tif (tools.length === CHROME_DEVTOOLS_TOOL_NAMES.length) {\n\t\treturn `all available (${tools.length}/${CHROME_DEVTOOLS_TOOL_NAMES.length} selected)`;\n\t}\n\tif (tools.length === 0)\n\t\treturn `all unavailable (0/${CHROME_DEVTOOLS_TOOL_NAMES.length} selected)`;\n\treturn `${tools.length}/${CHROME_DEVTOOLS_TOOL_NAMES.length} selected: ${tools.join(\", \")}`;\n}\n\nfunction effectiveCatalog(owner: object): ChromeDevToolsToolName[] {\n\treturn webMcpEnabled(owner)\n\t\t? [...CHROME_DEVTOOLS_TOOL_NAMES]\n\t\t: [...CORE_CHROME_DEVTOOLS_TOOL_NAMES];\n}\n\nasync function persistSettings(selectedTools: readonly ChromeDevToolsToolName[]) {\n\tawait saveSettings({ tools: [...selectedTools], updatedAt: Date.now() });\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["unique"]
7
+ }