From 0685879a7f46856a415b19fd042f0affbae167b7 Mon Sep 17 00:00:00 2001 From: Sean McGuire Date: Wed, 10 Jun 2026 14:35:16 -0700 Subject: [PATCH 1/8] wip --- .claude-plugin/marketplace.json | 15 + README.md | 1 + skills/webmcp-gen/.gitignore | 4 + skills/webmcp-gen/LICENSE.txt | 21 + skills/webmcp-gen/SKILL.md | 127 ++ skills/webmcp-gen/package.json | 9 + skills/webmcp-gen/pnpm-lock.yaml | 2054 ++++++++++++++++++++++++ skills/webmcp-gen/scripts/compile.mjs | 179 +++ skills/webmcp-gen/scripts/scaffold.mjs | 97 ++ skills/webmcp-gen/scripts/validate.mjs | 155 ++ 10 files changed, 2662 insertions(+) create mode 100644 skills/webmcp-gen/.gitignore create mode 100644 skills/webmcp-gen/LICENSE.txt create mode 100644 skills/webmcp-gen/SKILL.md create mode 100644 skills/webmcp-gen/package.json create mode 100644 skills/webmcp-gen/pnpm-lock.yaml create mode 100644 skills/webmcp-gen/scripts/compile.mjs create mode 100644 skills/webmcp-gen/scripts/scaffold.mjs create mode 100644 skills/webmcp-gen/scripts/validate.mjs diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index bba1a258..8a4b8f00 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -83,6 +83,21 @@ "skills": [ "./skills/safe-browser" ] + }, + { + "name": "webmcp-gen", + "source": "./", + "description": "Author, compile, and validate site-specific WebMCP init scripts from a target URL and desired tool capability.", + "version": "0.0.1", + "author": { + "name": "Browserbase" + }, + "category": "automation", + "keywords": ["webmcp", "stagehand", "browser", "automation", "tool-generation", "chrome-devtools"], + "strict": false, + "skills": [ + "./skills/webmcp-gen" + ] } ] } diff --git a/README.md b/README.md index 03d44f26..b47fc402 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ This plugin includes the following skills (see `skills/` for details): | [site-debugger](skills/site-debugger/SKILL.md) | Diagnose and fix failing browser automations — analyzes bot detection, selectors, timing, auth, and captchas, then generates a tested site playbook | | [browser-trace](skills/browser-trace/SKILL.md) | Capture a full DevTools-protocol trace (CDP firehose, screenshots, DOM dumps) alongside any browser automation, then bisect the stream into per-page searchable buckets | | [safe-browser](skills/safe-browser/SKILL.md) | Build local Claude Agent SDK browser agents whose only browser capability is a CDP-gated `safe_browser` tool with domain allowlist enforcement | +| [webmcp-gen](skills/webmcp-gen/SKILL.md) | Author, compile, and validate site-specific WebMCP init scripts with the Stagehand WebMCP runtime | | [bb-usage](skills/bb-usage/SKILL.md) | Show Browserbase usage stats, session analytics, and cost forecasts in a terminal dashboard | | [cookie-sync](skills/cookie-sync/SKILL.md) | Sync cookies from local Chrome to a Browserbase persistent context so the browse CLI can access authenticated sites | | [fetch](skills/fetch/SKILL.md) | Fetch HTML or JSON from static pages without a browser session — inspect status codes, headers, follow redirects | diff --git a/skills/webmcp-gen/.gitignore b/skills/webmcp-gen/.gitignore new file mode 100644 index 00000000..5b30de00 --- /dev/null +++ b/skills/webmcp-gen/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +artifacts/ +*.log +.DS_Store diff --git a/skills/webmcp-gen/LICENSE.txt b/skills/webmcp-gen/LICENSE.txt new file mode 100644 index 00000000..f2f43974 --- /dev/null +++ b/skills/webmcp-gen/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Browserbase, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/skills/webmcp-gen/SKILL.md b/skills/webmcp-gen/SKILL.md new file mode 100644 index 00000000..0855aa89 --- /dev/null +++ b/skills/webmcp-gen/SKILL.md @@ -0,0 +1,127 @@ +--- +name: webmcp-gen +description: Create, compile, and validate site-specific WebMCP init scripts from a target URL and desired tool capability. Use when the user wants to author WebMCP tools for a website, produce a webmcp.init.js artifact, or test WebMCP registration and invocation through Stagehand. +compatibility: "Requires Node 18+, Chrome/Chromium with WebMCP testing flags, and the Stagehand package declared in this skill's package.json." +license: MIT +allowed-tools: Bash, Read, Grep, Edit, Write +--- + +# WebMCP Gen + +Author website-specific WebMCP tools by writing a manifest, compiling it to an init script, and validating that Chrome registers and invokes the tools. + +This skill does not call a nested agent. You are responsible for exploring the page, writing `manifest.json`, and iterating based on validation output. + +## Setup check + +From the skill directory, install the Stagehand dependency if it is not already installed: + +```bash +cd skills/webmcp-gen +pnpm install +``` + +The skill's `package.json` points at the published Stagehand package: + +```text +@browserbasehq/stagehand +``` + +## Workflow + +1. Pick an artifact slug with exactly one slash: + +```text +/ +``` + +Example: + +```text +example.com/page-context +``` + +2. Scaffold the artifact: + +```bash +node scripts/scaffold.mjs example.com/page-context --url https://example.com +``` + +3. Explore the target page with the `browse` CLI: + +```bash +browse open https://example.com --local +browse snapshot +browse get title +browse get url +browse get text body +browse get html body +``` + +Prefer `browse snapshot`, page text, and DOM inspection over screenshots unless visual layout matters. Use `browse stop` when exploration is complete. + +4. Edit `artifacts///manifest.json`. The manifest is the source of truth. + +5. Compile: + +```bash +node scripts/compile.mjs artifacts/example.com/page-context +``` + +6. Validate: + +```bash +node scripts/validate.mjs artifacts/example.com/page-context +``` + +7. If validation fails, inspect `eval.json` and `eval-report.md`, patch `manifest.json`, then compile and validate again. + +## Manifest contract + +```json +{ + "domain": "example.com", + "task": "page-context", + "url": "https://example.com", + "generatedAt": "2026-06-04T00:00:00.000Z", + "tools": [ + { + "name": "example_com_page_context", + "description": "Returns page context.", + "inputSchema": { + "type": "object", + "properties": {}, + "required": [] + }, + "implementation": { + "kind": "dom", + "source": "return { success: true, title: document.title, url: location.href };" + }, + "fixtureInput": {} + } + ] +} +``` + +## Authoring rules + +- `implementation.source` is inserted inside `async (input) => { ... }`; write JavaScript statements, not a full function wrapper. +- Return a JSON-serializable object. +- WebMCP code runs inside the browser page. Use browser-native APIs: `document`, `location`, `navigator`, and same-origin `fetch`. +- Do not use Playwright, Puppeteer, Stagehand, XPath helpers, or agent/browser commands inside `implementation.source`. +- `document.querySelector` and `querySelectorAll` must receive valid browser CSS selectors only. +- To find visible text, use `Array.from(document.querySelectorAll(...)).find((el) => (el.textContent || "").includes("..."))`. +- Do not include API keys, bearer tokens, cookies, localStorage secrets, or user credentials. +- Do not use `eval` or `new Function`. +- Avoid destructive actions unless the user explicitly asked for them. +- Make implementations defensive: check for missing elements and return structured `{ success: false, error: "..." }` responses. + +## Output layout + +```text +artifacts/// + manifest.json + webmcp.init.js + eval.json + eval-report.md +``` diff --git a/skills/webmcp-gen/package.json b/skills/webmcp-gen/package.json new file mode 100644 index 00000000..635bd5fa --- /dev/null +++ b/skills/webmcp-gen/package.json @@ -0,0 +1,9 @@ +{ + "name": "webmcp-gen-skill", + "version": "0.1.0", + "private": true, + "type": "module", + "dependencies": { + "@browserbasehq/stagehand": "3.6.0-alpha-fd42e65bb84825bdb7341a4953472db1ff774989" + } +} diff --git a/skills/webmcp-gen/pnpm-lock.yaml b/skills/webmcp-gen/pnpm-lock.yaml new file mode 100644 index 00000000..eaad39e4 --- /dev/null +++ b/skills/webmcp-gen/pnpm-lock.yaml @@ -0,0 +1,2054 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@browserbasehq/stagehand': + specifier: 3.6.0-alpha-fd42e65bb84825bdb7341a4953472db1ff774989 + version: 3.6.0-alpha-fd42e65bb84825bdb7341a4953472db1ff774989(zod@4.4.3) + +packages: + + '@ai-sdk/amazon-bedrock@3.0.101': + resolution: {integrity: sha512-MU4KXBasSVTcP9U0mtfcnW9ME8fo9Hsf9ZOaz0SK0qHAYwxck9Dmh4dyBGZqcopYHkhYQPskTzYJq0ARm0hHsg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/anthropic@2.0.81': + resolution: {integrity: sha512-0iqx9hZc9xqdhxOdZkYJAKuCs9o+5a86gStYl0M7IBZzmx6jTDrynXiOigDjH3SQrmLclLCspTjW5E6YFrlyHQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/azure@2.0.110': + resolution: {integrity: sha512-jlOfvtIBwphaSgpIyjEJL4Ham5wB5B6dV+Or0zVvcoexAYaT3Mb2nppyBHZ56A0IX15IPC0xtwqYPw9E3U5q6g==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/cerebras@1.0.44': + resolution: {integrity: sha512-2w7+jq0bWEF6McgWPb2gjaEx1TpqdUq4eyX/gPLTp7HzfDZKEVmmVXRvnKvjzBP/VH7xW4OT5jhTpTPTfYNYYQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/deepseek@1.0.42': + resolution: {integrity: sha512-EhExHGpJnZsaeGF7f6DQZOI5/YjzB+y0aWFcA4EEpyGzrEH1aGsyCL465MJNXyigxOCCOhWqnt8Q1u69qYFSrQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/gateway@2.0.98': + resolution: {integrity: sha512-JNMc5Fbz8AwiLIR3Ar/lV2egbLFE+A5nfwbRKrdfgusoVN2VjgMX2U2KCLux5iWD/Q9+rg9+njHPZNw4HmzBJQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/google-vertex@3.0.141': + resolution: {integrity: sha512-+PjbZu63x+7RABQpAnNcJ0+EEZjKt3nQESQszA4Gyv9rLajob+FvxRJWeiLcKDsGIQdEFBknDrI5KLLSm7Doeg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/google@2.0.74': + resolution: {integrity: sha512-Lhw1742RXc+4pRIvqVXa0jdl5+qdpmw8lj0lm6OchUg9rVGHzymlaxe7CDiYX5U2af4jbjKeTY22LDi3bIycgQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/groq@2.0.40': + resolution: {integrity: sha512-1EL8D1tyjOKjCFUt8XspDoA6zxDcalMsLR2O56ji8QklWsAPaf4TuMJAvf5x5KDrkuJaSAjk94KvPH5hOX+VNQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/mistral@2.0.33': + resolution: {integrity: sha512-oBR9nJQ8TRFU0JIIXF+0cFTo8VVEreA1V8AMD3c77BJj/1NUSBLrhyqAbX9k7YAtztvZHUdFcm3+vK8KIx0sUQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/openai-compatible@1.0.39': + resolution: {integrity: sha512-001hdQPPXxYBWrz5d+eAmBVYmwzsB+guIey1DFXi1ZEE5H3j7fRrhPpX55MdM9Fle2DS7WZ8b3qkumCIWE92YQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/openai@2.0.106': + resolution: {integrity: sha512-EFC0rpo1wfe4HIz5KZCE72edP2J7fOeR7wPXzjCDljaTRB1wectKDIKRLowpU4F0mbcJ+XScAsoYNPK/Z20aVQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/perplexity@2.0.30': + resolution: {integrity: sha512-ymXWoItR4tRCIQlJcpn0zk4jBUU+j4SDnliz/z1f5U6rWxNY1ttxFCk4uZ+6Zt9e3VjQTpA9FK6cOJt18JRrKQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider-utils@3.0.25': + resolution: {integrity: sha512-CvsRu+32Y8a167s+lrIBtsybvgTHp8j9y+6BeTvLeoW3Q+okw/b4CnNUFOLIXsRaKHQKAH+IHNJPYWywfpw0LA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider@2.0.3': + resolution: {integrity: sha512-h88OPkavHTiN9tMn2l5awAznGB0lXzjcLhgR1/rvjB2zlLprsNxbM2tt6OJsHUxduLC3klq0/eqaSf6fX5XVww==} + engines: {node: '>=18'} + + '@ai-sdk/togetherai@1.0.42': + resolution: {integrity: sha512-V9reHPfWeaIt6fu03lVbjZDuxfdplS5jdmzVchVBeUug9VqIK+9KQELcPvdWKdxf+ov+sCoShN/O6dYfPPD5Ng==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/xai@2.0.73': + resolution: {integrity: sha512-U+/rdtqgDcloNSX7TIdRjYQooVydYdauQvLSP74oQcnE5N0/DD81yi+RvQXYYq47dDIn2H4exgr7XkBm4x1yDw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@anthropic-ai/sdk@0.39.0': + resolution: {integrity: sha512-eMyDIPRZbt1CCLErRCi3exlAvNkBtRe+kW5vvJyef93PmNr/clstYgHhtvmkxN82nlKgzyGPCyGxrm0JQ1ZIdg==} + + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/types@3.973.12': + resolution: {integrity: sha512-43ajd1NF0RMgX5k0hxCNUyEdrtFUsb2aHT2QvpktSC/2Eyb2Jr/JPVqdp0XIoaHWikZJq5tNWSLO6kB5q2eMCA==} + engines: {node: '>=20.0.0'} + + '@browserbasehq/sdk@2.14.0': + resolution: {integrity: sha512-DqVfjlgt74vPWfWiCp4VPtiMNJxg2yBZwio2uOfnpV1aJM0OWZR4AJrt/4df+xgQQ/guRpds5do41ycrDaYt3w==} + + '@browserbasehq/stagehand@3.6.0-alpha-fd42e65bb84825bdb7341a4953472db1ff774989': + resolution: {integrity: sha512-U5rgh1IKNULbJXsNgstynWhMC7C0Phb5bYbCjXdSS6ZTFxpy2VvGFL3CKgfQIgHIDoujDrqIe8WRim1+CybvgA==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + patchright-core: ^1.55.2 + playwright-core: ^1.55.1 + puppeteer-core: ^24.43.0 + zod: ^3.25.76 || ^4.2.0 + peerDependenciesMeta: + patchright-core: + optional: true + playwright-core: + optional: true + puppeteer-core: + optional: true + + '@google/genai@1.52.0': + resolution: {integrity: sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==} + engines: {node: '>=20.0.0'} + peerDependencies: + '@modelcontextprotocol/sdk': ^1.25.2 + peerDependenciesMeta: + '@modelcontextprotocol/sdk': + optional: true + + '@hono/node-server@1.19.14': + resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} + engines: {node: '>=18.14.1'} + peerDependencies: + hono: ^4 + + '@modelcontextprotocol/sdk@1.29.0': + resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==} + engines: {node: '>=18'} + peerDependencies: + '@cfworker/json-schema': ^4.1.1 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + '@cfworker/json-schema': + optional: true + + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.5': + resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==} + + '@protobufjs/eventemitter@1.1.1': + resolution: {integrity: sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==} + + '@protobufjs/fetch@1.1.1': + resolution: {integrity: sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.2': + resolution: {integrity: sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.1': + resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} + + '@smithy/core@3.24.6': + resolution: {integrity: sha512-wBXDRup6UU97VKyaiRo8AssnfStPtG0oAAfpq/bC0a1YYau8pM86YB4kM6ccoVi1mS8l/UHbn9oDM+7uozr/ug==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-codec@4.3.6': + resolution: {integrity: sha512-Ussyv240JxwQP8AmkYdm26wGP/1I8QmIv0ZosgDJDlSzD73FEdj1BOpXMc06VrxX5KxTKhadFNomT2SWutUnpg==} + engines: {node: '>=18.0.0'} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/types@4.14.3': + resolution: {integrity: sha512-YupL0ZWmFtJexUN2cHzkvvF/b9pKrtAIfT1o7/oY/Ppu8IYeZ+lDPM5vZdQJaSeA132dJCqojjGC9NhXeF71VQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@4.3.6': + resolution: {integrity: sha512-tAa4sePYB7mlJzdYbdBqdv37KwFKWixmM/r3ihcI0HFOVjf+a5oGvtcLXcGm4S1bY4DFsLAIOHgjubtp+oRufw==} + engines: {node: '>=18.0.0'} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@types/node-fetch@2.6.13': + resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==} + + '@types/node@18.19.130': + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} + + '@types/node@25.9.2': + resolution: {integrity: sha512-G05zqtJhcDLb8uslf5EjCxXg9G1KQxiV8OS0R26IC//Eoyitzqe8z37I7cqvnZlrlSfgocQRfSn/AHBZJJFyGw==} + + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + + '@vercel/oidc@3.1.0': + resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==} + engines: {node: '>= 20'} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + ai@5.0.197: + resolution: {integrity: sha512-iUzFb2M3ZUL/Bbmfonh75DIZ354svWO5xh8VPC2wYNR6zzEMFghPOlJG5rtEpqRa037lHfdcjt0qmzg3em/WDw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + + aws4fetch@1.0.20: + resolution: {integrity: sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + + body-parser@2.2.2: + resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} + engines: {node: '>=18'} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + bufferutil@4.1.0: + resolution: {integrity: sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==} + engines: {node: '>=6.14.2'} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + chrome-launcher@1.2.1: + resolution: {integrity: sha512-qmFR5PLMzHyuNJHwOloHPAHhbaNglkfeV/xDtt5b7xiFFyU1I+AZZX0PYseMuhenJSSirgxELYIbswcoc+5H4A==} + engines: {node: '>=12.13.0'} + hasBin: true + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + content-disposition@1.1.0: + resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} + engines: {node: '>=18'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + content-type@2.0.0: + resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} + engines: {node: '>=18'} + + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + cors@2.8.6: + resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} + engines: {node: '>= 0.10'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + devtools-protocol@0.0.1642743: + resolution: {integrity: sha512-vTCGze95hGFayPNUXv2H/3cNt/Kqv3J7XqS519j7U8HYhmtD6+eVEPHp6nRHD64dDXJ022TU4reAYhjYyuxm8Q==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + eventsource-parser@3.1.0: + resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} + engines: {node: '>=18.0.0'} + + eventsource@3.0.7: + resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} + engines: {node: '>=18.0.0'} + + express-rate-limit@8.5.2: + resolution: {integrity: sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==} + engines: {node: '>= 16'} + peerDependencies: + express: '>= 4.11' + + express@5.2.1: + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} + engines: {node: '>= 18'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-copy@4.0.3: + resolution: {integrity: sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} + + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + + fetch-cookie@3.2.0: + resolution: {integrity: sha512-n61pQIxP25C6DRhcJxn7BDzgHP/+S56Urowb5WFxtcRMpU6drqXD90xjyAsVQYsNSNNVbaCcYY1DuHsdkZLuiA==} + + finalhandler@2.1.1: + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} + + form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gaxios@7.1.5: + resolution: {integrity: sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==} + engines: {node: '>=18'} + + gcp-metadata@8.1.2: + resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} + engines: {node: '>=18'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + google-auth-library@10.7.0: + resolution: {integrity: sha512-QpTAbNJ36TliZLx3TTtahR8HG0hN9RllL1e3FymOvQSIKK8JmgV58H924ub2wa2DsS3ANjjP1Aw1N+Ramc8hqQ==} + engines: {node: '>=18'} + + google-logging-utils@1.1.3: + resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==} + engines: {node: '>=14'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + + hono@4.12.25: + resolution: {integrity: sha512-2NFaIyNVgJmBs/ecmtGzlmluTFs5cHEWGTdu0t1HBwYzoGXOL5nUQBRMXsXWla5i4KkG//QMzVP88m1+I3fdAQ==} + engines: {node: '>=16.9.0'} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ip-address@10.2.0: + resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} + engines: {node: '>= 12'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jose@6.2.3: + resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} + + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-schema-typed@8.0.2: + resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + + jws@4.0.1: + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + + lighthouse-logger@2.0.2: + resolution: {integrity: sha512-vWl2+u5jgOQuZR55Z1WM0XDdrJT6mzMP8zHUct7xTlWhuQs+eV0g+QL0RQdFjT54zVmbhLCP8vIVpy1wGn/gCg==} + + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + + marky@1.3.0: + resolution: {integrity: sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + node-gyp-build@4.8.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + hasBin: true + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + ollama-ai-provider-v2@1.5.5: + resolution: {integrity: sha512-1YwTFdPjhPNHny/DrOHO+s8oVGGIE5Jib61/KnnjPRNWQhVVimrJJdaAX3e6nNRRDXrY5zbb9cfm2+yVvgsrqw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^4.0.16 + + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + openai@4.104.0: + resolution: {integrity: sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.23.8 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-to-regexp@8.4.2: + resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} + + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-abstract-transport@3.0.0: + resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} + + pino-pretty@13.1.3: + resolution: {integrity: sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==} + hasBin: true + + pino-std-serializers@7.1.0: + resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==} + + pino@9.14.0: + resolution: {integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==} + hasBin: true + + pkce-challenge@5.0.1: + resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} + engines: {node: '>=16.20.0'} + + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + + protobufjs@7.6.3: + resolution: {integrity: sha512-+k0vdJKNdW+Vu+dYe8tZA/VvQb6XKNWexC6URwBFXxNnjLJz9nQJCemGyNgRAWD+B7+nGNc9qMPGwcD7s4nzUw==} + engines: {node: '>=12.0.0'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + + qs@6.15.2: + resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} + engines: {node: '>=0.6'} + + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@3.0.2: + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} + engines: {node: '>= 0.10'} + + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + secure-json-parse@4.1.0: + resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} + + send@1.2.1: + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} + engines: {node: '>= 18'} + + serve-static@2.2.1: + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} + engines: {node: '>= 18'} + + set-cookie-parser@2.7.2: + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} + engines: {node: '>= 0.4'} + + sonic-boom@4.2.1: + resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} + + thread-stream@3.2.0: + resolution: {integrity: sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==} + + tldts-core@7.4.2: + resolution: {integrity: sha512-nwEyF4vl4RSJjwSjBUmOSxc3BFPoIFdlRthJ6e+5v9P3bHNsoD06UjuqMUspqp7vsEZ1beaHi1km+optiE17yA==} + + tldts@7.4.2: + resolution: {integrity: sha512-kCwffuaH8ntKtygnWe1b4BJKWiCUH30n5KfoTr6IchcXOwR7chAOFJxFrH3vjANafUYrIA4a7SDL+nn7SiR4Sw==} + hasBin: true + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tough-cookie@6.0.1: + resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} + engines: {node: '>=16'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-is@2.1.0: + resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} + engines: {node: '>= 18'} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + uuid@11.1.1: + resolution: {integrity: sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==} + hasBin: true + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + + web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + zod-to-json-schema@3.25.2: + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + peerDependencies: + zod: ^3.25.28 || ^4 + + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + +snapshots: + + '@ai-sdk/amazon-bedrock@3.0.101(zod@4.4.3)': + dependencies: + '@ai-sdk/anthropic': 2.0.81(zod@4.4.3) + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + '@smithy/eventstream-codec': 4.3.6 + '@smithy/util-utf8': 4.3.6 + aws4fetch: 1.0.20 + zod: 4.4.3 + optional: true + + '@ai-sdk/anthropic@2.0.81(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + '@ai-sdk/azure@2.0.110(zod@4.4.3)': + dependencies: + '@ai-sdk/deepseek': 1.0.42(zod@4.4.3) + '@ai-sdk/openai': 2.0.106(zod@4.4.3) + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + '@ai-sdk/cerebras@1.0.44(zod@4.4.3)': + dependencies: + '@ai-sdk/openai-compatible': 1.0.39(zod@4.4.3) + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + '@ai-sdk/deepseek@1.0.42(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + '@ai-sdk/gateway@2.0.98(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + '@vercel/oidc': 3.1.0 + zod: 4.4.3 + + '@ai-sdk/google-vertex@3.0.141(zod@4.4.3)': + dependencies: + '@ai-sdk/anthropic': 2.0.81(zod@4.4.3) + '@ai-sdk/google': 2.0.74(zod@4.4.3) + '@ai-sdk/openai-compatible': 1.0.39(zod@4.4.3) + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + google-auth-library: 10.7.0 + zod: 4.4.3 + transitivePeerDependencies: + - supports-color + optional: true + + '@ai-sdk/google@2.0.74(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + '@ai-sdk/groq@2.0.40(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + '@ai-sdk/mistral@2.0.33(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + '@ai-sdk/openai-compatible@1.0.39(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + '@ai-sdk/openai@2.0.106(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + '@ai-sdk/perplexity@2.0.30(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + '@ai-sdk/provider-utils@3.0.25(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.1.0 + zod: 4.4.3 + + '@ai-sdk/provider@2.0.3': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/togetherai@1.0.42(zod@4.4.3)': + dependencies: + '@ai-sdk/openai-compatible': 1.0.39(zod@4.4.3) + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + '@ai-sdk/xai@2.0.73(zod@4.4.3)': + dependencies: + '@ai-sdk/openai-compatible': 1.0.39(zod@4.4.3) + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + '@anthropic-ai/sdk@0.39.0': + dependencies: + '@types/node': 18.19.130 + '@types/node-fetch': 2.6.13 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.12 + tslib: 2.8.1 + optional: true + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.973.12 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + optional: true + + '@aws-sdk/types@3.973.12': + dependencies: + '@smithy/types': 4.14.3 + tslib: 2.8.1 + optional: true + + '@browserbasehq/sdk@2.14.0': + dependencies: + '@types/node': 18.19.130 + '@types/node-fetch': 2.6.13 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + '@browserbasehq/stagehand@3.6.0-alpha-fd42e65bb84825bdb7341a4953472db1ff774989(zod@4.4.3)': + dependencies: + '@ai-sdk/provider': 2.0.3 + '@anthropic-ai/sdk': 0.39.0 + '@browserbasehq/sdk': 2.14.0 + '@google/genai': 1.52.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(bufferutil@4.1.0) + '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3) + ai: 5.0.197(zod@4.4.3) + devtools-protocol: 0.0.1642743 + fetch-cookie: 3.2.0 + openai: 4.104.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.4.3) + pino: 9.14.0 + pino-pretty: 13.1.3 + uuid: 11.1.1 + ws: 8.21.0(bufferutil@4.1.0) + zod: 4.4.3 + zod-to-json-schema: 3.25.2(zod@4.4.3) + optionalDependencies: + '@ai-sdk/amazon-bedrock': 3.0.101(zod@4.4.3) + '@ai-sdk/anthropic': 2.0.81(zod@4.4.3) + '@ai-sdk/azure': 2.0.110(zod@4.4.3) + '@ai-sdk/cerebras': 1.0.44(zod@4.4.3) + '@ai-sdk/deepseek': 1.0.42(zod@4.4.3) + '@ai-sdk/google': 2.0.74(zod@4.4.3) + '@ai-sdk/google-vertex': 3.0.141(zod@4.4.3) + '@ai-sdk/groq': 2.0.40(zod@4.4.3) + '@ai-sdk/mistral': 2.0.33(zod@4.4.3) + '@ai-sdk/openai': 2.0.106(zod@4.4.3) + '@ai-sdk/perplexity': 2.0.30(zod@4.4.3) + '@ai-sdk/togetherai': 1.0.42(zod@4.4.3) + '@ai-sdk/xai': 2.0.73(zod@4.4.3) + bufferutil: 4.1.0 + chrome-launcher: 1.2.1 + ollama-ai-provider-v2: 1.5.5(zod@4.4.3) + transitivePeerDependencies: + - '@cfworker/json-schema' + - encoding + - supports-color + - utf-8-validate + + '@google/genai@1.52.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(bufferutil@4.1.0)': + dependencies: + google-auth-library: 10.7.0 + p-retry: 4.6.2 + protobufjs: 7.6.3 + ws: 8.21.0(bufferutil@4.1.0) + optionalDependencies: + '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@hono/node-server@1.19.14(hono@4.12.25)': + dependencies: + hono: 4.12.25 + + '@modelcontextprotocol/sdk@1.29.0(zod@4.4.3)': + dependencies: + '@hono/node-server': 1.19.14(hono@4.12.25) + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + content-type: 1.0.5 + cors: 2.8.6 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.1.0 + express: 5.2.1 + express-rate-limit: 8.5.2(express@5.2.1) + hono: 4.12.25 + jose: 6.2.3 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 4.4.3 + zod-to-json-schema: 3.25.2(zod@4.4.3) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/api@1.9.0': {} + + '@pinojs/redact@0.4.0': {} + + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.5': {} + + '@protobufjs/eventemitter@1.1.1': {} + + '@protobufjs/fetch@1.1.1': + dependencies: + '@protobufjs/aspromise': 1.1.2 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.2': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.1': {} + + '@smithy/core@3.24.6': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.14.3 + tslib: 2.8.1 + optional: true + + '@smithy/eventstream-codec@4.3.6': + dependencies: + '@smithy/core': 3.24.6 + tslib: 2.8.1 + optional: true + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@smithy/types@4.14.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + optional: true + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + optional: true + + '@smithy/util-utf8@4.3.6': + dependencies: + '@smithy/core': 3.24.6 + tslib: 2.8.1 + optional: true + + '@standard-schema/spec@1.1.0': {} + + '@types/node-fetch@2.6.13': + dependencies: + '@types/node': 18.19.130 + form-data: 4.0.5 + + '@types/node@18.19.130': + dependencies: + undici-types: 5.26.5 + + '@types/node@25.9.2': + dependencies: + undici-types: 7.24.6 + + '@types/retry@0.12.0': {} + + '@vercel/oidc@3.1.0': {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + accepts@2.0.0: + dependencies: + mime-types: 3.0.2 + negotiator: 1.0.0 + + agent-base@7.1.4: {} + + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + + ai@5.0.197(zod@4.4.3): + dependencies: + '@ai-sdk/gateway': 2.0.98(zod@4.4.3) + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + '@opentelemetry/api': 1.9.0 + zod: 4.4.3 + + ajv-formats@3.0.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.2 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + asynckit@0.4.0: {} + + atomic-sleep@1.0.0: {} + + aws4fetch@1.0.20: + optional: true + + base64-js@1.5.1: {} + + bignumber.js@9.3.1: {} + + body-parser@2.2.2: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 4.4.3 + http-errors: 2.0.1 + iconv-lite: 0.7.2 + on-finished: 2.4.1 + qs: 6.15.2 + raw-body: 3.0.2 + type-is: 2.1.0 + transitivePeerDependencies: + - supports-color + + buffer-equal-constant-time@1.0.1: {} + + bufferutil@4.1.0: + dependencies: + node-gyp-build: 4.8.4 + optional: true + + bytes@3.1.2: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + chrome-launcher@1.2.1: + dependencies: + '@types/node': 25.9.2 + escape-string-regexp: 4.0.0 + is-wsl: 2.2.0 + lighthouse-logger: 2.0.2 + transitivePeerDependencies: + - supports-color + optional: true + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + content-disposition@1.1.0: {} + + content-type@1.0.5: {} + + content-type@2.0.0: {} + + cookie-signature@1.2.2: {} + + cookie@0.7.2: {} + + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + data-uri-to-buffer@4.0.1: {} + + dateformat@4.6.3: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + delayed-stream@1.0.0: {} + + depd@2.0.0: {} + + devtools-protocol@0.0.1642743: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + ee-first@1.1.1: {} + + encodeurl@2.0.0: {} + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + escape-html@1.0.3: {} + + escape-string-regexp@4.0.0: + optional: true + + etag@1.8.1: {} + + event-target-shim@5.0.1: {} + + eventsource-parser@3.1.0: {} + + eventsource@3.0.7: + dependencies: + eventsource-parser: 3.1.0 + + express-rate-limit@8.5.2(express@5.2.1): + dependencies: + express: 5.2.1 + ip-address: 10.2.0 + + express@5.2.1: + dependencies: + accepts: 2.0.0 + body-parser: 2.2.2 + content-disposition: 1.1.0 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.3 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.1 + fresh: 2.0.0 + http-errors: 2.0.1 + merge-descriptors: 2.0.0 + mime-types: 3.0.2 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.15.2 + range-parser: 1.2.1 + router: 2.2.0 + send: 1.2.1 + serve-static: 2.2.1 + statuses: 2.0.2 + type-is: 2.1.0 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + extend@3.0.2: {} + + fast-copy@4.0.3: {} + + fast-deep-equal@3.1.3: {} + + fast-safe-stringify@2.1.1: {} + + fast-uri@3.1.2: {} + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + + fetch-cookie@3.2.0: + dependencies: + set-cookie-parser: 2.7.2 + tough-cookie: 6.0.1 + + finalhandler@2.1.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + form-data-encoder@1.7.2: {} + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.4 + mime-types: 2.1.35 + + formdata-node@4.4.1: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + + forwarded@0.2.0: {} + + fresh@2.0.0: {} + + function-bind@1.1.2: {} + + gaxios@7.1.5: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + node-fetch: 3.3.2 + transitivePeerDependencies: + - supports-color + + gcp-metadata@8.1.2: + dependencies: + gaxios: 7.1.5 + google-logging-utils: 1.1.3 + json-bigint: 1.0.0 + transitivePeerDependencies: + - supports-color + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + google-auth-library@10.7.0: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 7.1.5 + gcp-metadata: 8.1.2 + google-logging-utils: 1.1.3 + jws: 4.0.1 + transitivePeerDependencies: + - supports-color + + google-logging-utils@1.1.3: {} + + gopd@1.2.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + help-me@5.0.0: {} + + hono@4.12.25: {} + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 + + inherits@2.0.4: {} + + ip-address@10.2.0: {} + + ipaddr.js@1.9.1: {} + + is-docker@2.2.1: + optional: true + + is-promise@4.0.0: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + optional: true + + isexe@2.0.0: {} + + jose@6.2.3: {} + + joycon@3.1.1: {} + + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.1 + + json-schema-traverse@1.0.0: {} + + json-schema-typed@8.0.2: {} + + json-schema@0.4.0: {} + + jwa@2.0.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.1: + dependencies: + jwa: 2.0.1 + safe-buffer: 5.2.1 + + lighthouse-logger@2.0.2: + dependencies: + debug: 4.4.3 + marky: 1.3.0 + transitivePeerDependencies: + - supports-color + optional: true + + long@5.3.2: {} + + marky@1.3.0: + optional: true + + math-intrinsics@1.1.0: {} + + media-typer@1.1.0: {} + + merge-descriptors@2.0.0: {} + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + + minimist@1.2.8: {} + + ms@2.1.3: {} + + negotiator@1.0.0: {} + + node-domexception@1.0.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + + node-gyp-build@4.8.4: + optional: true + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + ollama-ai-provider-v2@1.5.5(zod@4.4.3): + dependencies: + '@ai-sdk/provider': 2.0.3 + '@ai-sdk/provider-utils': 3.0.25(zod@4.4.3) + zod: 4.4.3 + optional: true + + on-exit-leak-free@2.1.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + openai@4.104.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.4.3): + dependencies: + '@types/node': 18.19.130 + '@types/node-fetch': 2.6.13 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + optionalDependencies: + ws: 8.21.0(bufferutil@4.1.0) + zod: 4.4.3 + transitivePeerDependencies: + - encoding + + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + parseurl@1.3.3: {} + + path-key@3.1.1: {} + + path-to-regexp@8.4.2: {} + + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-abstract-transport@3.0.0: + dependencies: + split2: 4.2.0 + + pino-pretty@13.1.3: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 4.0.3 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 3.0.0 + pump: 3.0.4 + secure-json-parse: 4.1.0 + sonic-boom: 4.2.1 + strip-json-comments: 5.0.3 + + pino-std-serializers@7.1.0: {} + + pino@9.14.0: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.1.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.1 + thread-stream: 3.2.0 + + pkce-challenge@5.0.1: {} + + process-warning@5.0.0: {} + + protobufjs@7.6.3: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/eventemitter': 1.1.1 + '@protobufjs/fetch': 1.1.1 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.2 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.1 + '@types/node': 25.9.2 + long: 5.3.2 + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + qs@6.15.2: + dependencies: + side-channel: 1.1.1 + + quick-format-unescaped@4.0.4: {} + + range-parser@1.2.1: {} + + raw-body@3.0.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.7.2 + unpipe: 1.0.0 + + real-require@0.2.0: {} + + require-from-string@2.0.2: {} + + retry@0.13.1: {} + + router@2.2.0: + dependencies: + debug: 4.4.3 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.4.2 + transitivePeerDependencies: + - supports-color + + safe-buffer@5.2.1: {} + + safe-stable-stringify@2.5.0: {} + + safer-buffer@2.1.2: {} + + secure-json-parse@4.1.0: {} + + send@1.2.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.1 + mime-types: 3.0.2 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serve-static@2.2.1: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.1 + transitivePeerDependencies: + - supports-color + + set-cookie-parser@2.7.2: {} + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + sonic-boom@4.2.1: + dependencies: + atomic-sleep: 1.0.0 + + split2@4.2.0: {} + + statuses@2.0.2: {} + + strip-json-comments@5.0.3: {} + + thread-stream@3.2.0: + dependencies: + real-require: 0.2.0 + + tldts-core@7.4.2: {} + + tldts@7.4.2: + dependencies: + tldts-core: 7.4.2 + + toidentifier@1.0.1: {} + + tough-cookie@6.0.1: + dependencies: + tldts: 7.4.2 + + tr46@0.0.3: {} + + tslib@2.8.1: + optional: true + + type-is@2.1.0: + dependencies: + content-type: 2.0.0 + media-typer: 1.1.0 + mime-types: 3.0.2 + + undici-types@5.26.5: {} + + undici-types@7.24.6: {} + + unpipe@1.0.0: {} + + uuid@11.1.1: {} + + vary@1.1.2: {} + + web-streams-polyfill@3.3.3: {} + + web-streams-polyfill@4.0.0-beta.3: {} + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wrappy@1.0.2: {} + + ws@8.21.0(bufferutil@4.1.0): + optionalDependencies: + bufferutil: 4.1.0 + + zod-to-json-schema@3.25.2(zod@4.4.3): + dependencies: + zod: 4.4.3 + + zod@4.4.3: {} diff --git a/skills/webmcp-gen/scripts/compile.mjs b/skills/webmcp-gen/scripts/compile.mjs new file mode 100644 index 00000000..819720b5 --- /dev/null +++ b/skills/webmcp-gen/scripts/compile.mjs @@ -0,0 +1,179 @@ +#!/usr/bin/env node +import { readFile, writeFile } from "node:fs/promises"; +import path from "node:path"; + +const TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]{1,80}$/; +const IMPLEMENTATION_KINDS = new Set(["same_origin_fetch", "dom", "hybrid"]); + +function usage() { + return "Usage: compile.mjs "; +} + +function assertObject(value, label) { + if (!value || typeof value !== "object" || Array.isArray(value)) { + throw new Error(`${label} must be an object.`); + } +} + +function assertValidTool(tool) { + assertObject(tool, "Tool"); + if (!TOOL_NAME_PATTERN.test(String(tool.name || ""))) { + throw new Error(`Invalid tool name "${tool.name}". Use 1-80 letters, numbers, underscores, or hyphens.`); + } + if (!String(tool.description || "").trim()) { + throw new Error(`Tool "${tool.name}" is missing a description.`); + } + assertObject(tool.inputSchema, `Tool "${tool.name}" inputSchema`); + assertObject(tool.implementation, `Tool "${tool.name}" implementation`); + if (!IMPLEMENTATION_KINDS.has(tool.implementation.kind)) { + throw new Error(`Tool "${tool.name}" has an invalid implementation kind.`); + } + if (!String(tool.implementation.source || "").trim()) { + throw new Error(`Tool "${tool.name}" is missing implementation source.`); + } +} + +function assertValidManifest(manifest) { + assertObject(manifest, "Manifest"); + if (!String(manifest.domain || "").trim()) throw new Error("Manifest is missing domain."); + if (!String(manifest.task || "").trim()) throw new Error("Manifest is missing task."); + if (!String(manifest.url || "").trim()) throw new Error("Manifest is missing url."); + if (!Array.isArray(manifest.tools) || manifest.tools.length === 0) { + throw new Error("Manifest must contain at least one tool."); + } + for (const tool of manifest.tools) assertValidTool(tool); +} + +function indent(source, spaces) { + const prefix = " ".repeat(spaces); + return String(source) + .trim() + .split("\n") + .map((line) => `${prefix}${line}`) + .join("\n"); +} + +function serializeTool(tool) { + return `{ + name: ${JSON.stringify(tool.name)}, + description: ${JSON.stringify(tool.description)}, + inputSchema: ${JSON.stringify(tool.inputSchema, null, 6)}, + execute: withTimeout(async (input) => { +${indent(tool.implementation.source, 8)} + }, 30000), + }`; +} + +function emitWebMCPInitScript(manifest) { + assertValidManifest(manifest); + const tools = manifest.tools.map(serializeTool).join(",\n\n"); + + return `(() => { + const WEBMCP_GEN_TOOLS = [ + ${tools} + ]; + + function normalizeError(error) { + if (error instanceof Error) { + return { + name: error.name, + message: error.message, + stack: error.stack, + }; + } + return { message: String(error) }; + } + + function withTimeout(fn, timeoutMs) { + return async (input) => { + let timer; + try { + return await Promise.race([ + fn(input || {}), + new Promise((_, reject) => { + timer = setTimeout( + () => reject(new Error("WebMCP tool timed out")), + timeoutMs, + ); + }), + ]); + } catch (error) { + return { + success: false, + error: normalizeError(error), + }; + } finally { + if (timer) clearTimeout(timer); + } + }; + } + + function registerTools() { + if (!navigator.modelContext) { + return { + success: false, + error: "navigator.modelContext is not available.", + }; + } + + for (const tool of WEBMCP_GEN_TOOLS) { + try { + navigator.modelContext.unregisterTool(tool.name); + } catch { + // Tool may not exist yet. + } + navigator.modelContext.registerTool(tool); + } + + return { + success: true, + registeredTools: WEBMCP_GEN_TOOLS.map((tool) => tool.name), + }; + } + + window.__webmcpGenRegistration = registerTools(); +})(); +`; +} + +function staticChecks(manifest, source) { + const warnings = []; + const errors = []; + if (!source.includes("navigator.modelContext.registerTool")) { + errors.push("Generated script does not register WebMCP tools."); + } + for (const tool of manifest.tools) { + const implementationSource = String(tool.implementation.source || ""); + if (implementationSource.includes("page.") || implementationSource.includes("locator(")) { + warnings.push(`Tool "${tool.name}" may contain Playwright-style code; WebMCP implementations run in the page.`); + } + if (implementationSource.includes("eval(") || implementationSource.includes("new Function")) { + errors.push(`Tool "${tool.name}" uses eval/new Function.`); + } + } + return { passed: errors.length === 0, errors, warnings }; +} + +async function main() { + const artifactDir = process.argv[2]; + if (!artifactDir) throw new Error(usage()); + + const resolvedArtifactDir = path.resolve(process.cwd(), artifactDir); + const manifestPath = path.join(resolvedArtifactDir, "manifest.json"); + const manifest = JSON.parse(await readFile(manifestPath, "utf8")); + const source = emitWebMCPInitScript(manifest); + const checks = staticChecks(manifest, source); + if (!checks.passed) { + throw new Error(`Static checks failed:\n${checks.errors.map((error) => `- ${error}`).join("\n")}`); + } + await writeFile(path.join(resolvedArtifactDir, "webmcp.init.js"), source, "utf8"); + console.log(`Compiled WebMCP artifact at ${resolvedArtifactDir}`); + if (checks.warnings.length) { + console.log(`Warnings:\n${checks.warnings.map((warning) => `- ${warning}`).join("\n")}`); + } +} + +main().catch((error) => { + console.error(error instanceof Error ? error.message : String(error)); + process.exitCode = 1; +}); diff --git a/skills/webmcp-gen/scripts/scaffold.mjs b/skills/webmcp-gen/scripts/scaffold.mjs new file mode 100644 index 00000000..98bb41e0 --- /dev/null +++ b/skills/webmcp-gen/scripts/scaffold.mjs @@ -0,0 +1,97 @@ +#!/usr/bin/env node +import { mkdir, writeFile } from "node:fs/promises"; +import path from "node:path"; + +function parseArgs(argv) { + const [slug, ...rest] = argv; + const flags = {}; + for (let index = 0; index < rest.length; index += 1) { + const arg = rest[index]; + if (!arg.startsWith("--")) continue; + const key = arg.slice(2); + const next = rest[index + 1]; + if (next && !next.startsWith("--")) { + flags[key] = next; + index += 1; + } else { + flags[key] = true; + } + } + return { slug, flags }; +} + +function usage() { + return "Usage: scaffold.mjs / --url [--out artifacts]"; +} + +function parseSlug(slug) { + const parts = String(slug || "").split("/"); + if (parts.length !== 2 || !parts[0] || !parts[1]) { + throw new Error(`Slug must be / with exactly one slash.\n\n${usage()}`); + } + return { domain: parts[0], task: parts[1] }; +} + +function artifactDirFor(slug, outRoot) { + return path.resolve(process.cwd(), outRoot || "artifacts", slug); +} + +function toolNameFor(domain, task) { + return `${domain}_${task}`.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, ""); +} + +async function main() { + const { slug, flags } = parseArgs(process.argv.slice(2)); + const url = typeof flags.url === "string" ? flags.url : undefined; + if (!slug || !url) throw new Error(usage()); + + const { domain, task } = parseSlug(slug); + const artifactDir = artifactDirFor(slug, typeof flags.out === "string" ? flags.out : undefined); + await mkdir(artifactDir, { recursive: true }); + + const manifest = { + domain, + task, + url, + generatedAt: new Date().toISOString(), + tools: [ + { + name: toolNameFor(domain, task), + description: "Returns basic page context. Use this scaffold to validate WebMCP injection.", + inputSchema: { + type: "object", + properties: { + echo: { + type: "string", + description: "Optional value to echo in the response." + } + }, + additionalProperties: true + }, + implementation: { + kind: "dom", + source: `return { + success: true, + echo: input.echo ?? null, + page: { + title: document.title, + url: location.href, + h1: document.querySelector("h1")?.textContent?.trim() ?? null + } +};` + }, + fixtureInput: { + echo: "webmcp-gen validation" + } + } + ] + }; + + await writeFile(path.join(artifactDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`, "utf8"); + console.log(`Created WebMCP artifact at ${artifactDir}`); +} + +main().catch((error) => { + console.error(error instanceof Error ? error.message : String(error)); + process.exitCode = 1; +}); diff --git a/skills/webmcp-gen/scripts/validate.mjs b/skills/webmcp-gen/scripts/validate.mjs new file mode 100644 index 00000000..94a22d9b --- /dev/null +++ b/skills/webmcp-gen/scripts/validate.mjs @@ -0,0 +1,155 @@ +#!/usr/bin/env node +import { access, readFile, writeFile } from "node:fs/promises"; +import path from "node:path"; +import { Stagehand } from "@browserbasehq/stagehand"; + +function usage() { + return "Usage: validate.mjs "; +} + +async function readManifest(artifactDir) { + return JSON.parse(await readFile(path.join(artifactDir, "manifest.json"), "utf8")); +} + +function outputLooksFailed(output) { + return output !== null && typeof output === "object" && "success" in output && output.success === false; +} + +async function writeEvalResult(artifactDir, result) { + await writeFile(path.join(artifactDir, "eval.json"), `${JSON.stringify(result, null, 2)}\n`, "utf8"); + const lines = [ + "# WebMCP Eval Report", + "", + `Status: ${result.status}`, + `URL: ${result.url}`, + "", + "## Tools", + "" + ]; + for (const tool of result.tools) { + lines.push(`- ${tool.name}: found=${tool.found} invoked=${tool.invoked} status=${tool.status ?? "n/a"}`); + if (tool.error) lines.push(` - error: ${tool.error}`); + } + if (result.errors.length) { + lines.push("", "## Errors", ""); + for (const error of result.errors) lines.push(`- ${error}`); + } + await writeFile(path.join(artifactDir, "eval-report.md"), `${lines.join("\n")}\n`, "utf8"); +} + +async function validateArtifact(artifactDir) { + const manifest = await readManifest(artifactDir); + const scriptPath = path.join(artifactDir, "webmcp.init.js"); + const errors = []; + const tools = []; + + try { + await access(scriptPath); + } catch { + const result = { + artifactDir, + url: manifest.url, + status: "failed", + tools, + errors: [`Missing webmcp.init.js. Run compile.mjs ${artifactDir} first.`] + }; + await writeEvalResult(artifactDir, result); + return result; + } + + const stagehand = new Stagehand({ + env: "LOCAL", + verbose: 1, + localBrowserLaunchOptions: { + args: ["--enable-features=WebMCPTesting,DevToolsWebMCPSupport"] + } + }); + + try { + await stagehand.init(); + const page = stagehand.context.pages()[0] ?? (await stagehand.context.newPage()); + await page.addInitScript({ path: scriptPath }); + await page.goto(manifest.url, { waitUntil: "load" }); + + const registeredTools = await page.listWebMCPTools({ timeoutMs: 1000 }); + + for (const expectedTool of manifest.tools) { + const foundTool = registeredTools.find((tool) => tool.name === expectedTool.name); + if (!foundTool) { + tools.push({ + name: expectedTool.name, + found: false, + invoked: false, + error: "Tool was not registered." + }); + continue; + } + + try { + const invocation = await page.invokeWebMCPTool( + expectedTool.name, + expectedTool.fixtureInput ?? {}, + { frameId: foundTool.frameId } + ); + const result = await invocation.result; + const error = result.errorText || outputLooksFailed(result.output) + ? result.errorText ?? "Tool returned an output with success=false." + : undefined; + tools.push({ + name: expectedTool.name, + found: true, + invoked: true, + status: result.status, + output: result.output, + ...(error ? { error } : {}) + }); + } catch (error) { + tools.push({ + name: expectedTool.name, + found: true, + invoked: false, + error: error instanceof Error ? error.message : String(error) + }); + } + } + } catch (error) { + errors.push(error instanceof Error ? error.message : String(error)); + } finally { + await stagehand.close().catch(() => {}); + } + + const status = errors.length === 0 && + tools.length === manifest.tools.length && + tools.every((tool) => tool.found && tool.invoked && tool.status === "Completed" && !tool.error) + ? "passed" + : "failed"; + + const result = { + artifactDir, + url: manifest.url, + status, + tools, + errors + }; + await writeEvalResult(artifactDir, result); + return result; +} + +async function main() { + const artifactDir = process.argv[2]; + if (!artifactDir) throw new Error(usage()); + const resolvedArtifactDir = path.resolve(process.cwd(), artifactDir); + const result = await validateArtifact(resolvedArtifactDir); + console.log(`Validation ${result.status}: ${resolvedArtifactDir}`); + for (const tool of result.tools) { + console.log(`- ${tool.name}: found=${tool.found} invoked=${tool.invoked} status=${tool.status ?? "n/a"}`); + if (tool.error) console.log(` error=${tool.error}`); + } + for (const error of result.errors) console.log(`Error: ${error}`); + if (result.status !== "passed") process.exitCode = 1; +} + +main().catch((error) => { + console.error(error instanceof Error ? error.message : String(error)); + process.exitCode = 1; +}); From 74421446395b5052fba6e5eeffa1ec7cdbdf7154 Mon Sep 17 00:00:00 2001 From: Sean McGuire Date: Wed, 10 Jun 2026 14:56:57 -0700 Subject: [PATCH 2/8] wip --- skills/webmcp-gen/SKILL.md | 12 +- skills/webmcp-gen/scripts/compile.mjs | 10 +- .../scripts/generate-stagehand-example.mjs | 117 ++++++++++++++++++ 3 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 skills/webmcp-gen/scripts/generate-stagehand-example.mjs diff --git a/skills/webmcp-gen/SKILL.md b/skills/webmcp-gen/SKILL.md index 0855aa89..7a30b401 100644 --- a/skills/webmcp-gen/SKILL.md +++ b/skills/webmcp-gen/SKILL.md @@ -68,13 +68,19 @@ Prefer `browse snapshot`, page text, and DOM inspection over screenshots unless node scripts/compile.mjs artifacts/example.com/page-context ``` -6. Validate: +6. Generate a runnable Stagehand example: + +```bash +node scripts/generate-stagehand-example.mjs artifacts/example.com/page-context +``` + +7. Validate: ```bash node scripts/validate.mjs artifacts/example.com/page-context ``` -7. If validation fails, inspect `eval.json` and `eval-report.md`, patch `manifest.json`, then compile and validate again. +8. If validation fails, inspect `eval.json` and `eval-report.md`, patch `manifest.json`, then compile and validate again. ## Manifest contract @@ -115,6 +121,7 @@ node scripts/validate.mjs artifacts/example.com/page-context - Do not use `eval` or `new Function`. - Avoid destructive actions unless the user explicitly asked for them. - Make implementations defensive: check for missing elements and return structured `{ success: false, error: "..." }` responses. +- Generated init scripts register WebMCP tools only in the top frame. ## Output layout @@ -122,6 +129,7 @@ node scripts/validate.mjs artifacts/example.com/page-context artifacts/// manifest.json webmcp.init.js + stagehand-example.mjs eval.json eval-report.md ``` diff --git a/skills/webmcp-gen/scripts/compile.mjs b/skills/webmcp-gen/scripts/compile.mjs index 819720b5..44bd13aa 100644 --- a/skills/webmcp-gen/scripts/compile.mjs +++ b/skills/webmcp-gen/scripts/compile.mjs @@ -4,6 +4,12 @@ import path from "node:path"; const TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]{1,80}$/; const IMPLEMENTATION_KINDS = new Set(["same_origin_fetch", "dom", "hybrid"]); +const PLAYWRIGHT_STYLE_PATTERNS = [ + /\bpage\.(goto|locator|click|fill|evaluate|waitFor|waitForSelector)\s*\(/, + /\bbrowser\.newPage\s*\(/, + /\bcontext\.newPage\s*\(/, + /\bawait\s+page\b/, +]; function usage() { return "Usage: compile.mjs "; @@ -69,6 +75,8 @@ function emitWebMCPInitScript(manifest) { const tools = manifest.tools.map(serializeTool).join(",\n\n"); return `(() => { + if (window.self !== window.top) return; + const WEBMCP_GEN_TOOLS = [ ${tools} ]; @@ -144,7 +152,7 @@ function staticChecks(manifest, source) { } for (const tool of manifest.tools) { const implementationSource = String(tool.implementation.source || ""); - if (implementationSource.includes("page.") || implementationSource.includes("locator(")) { + if (PLAYWRIGHT_STYLE_PATTERNS.some((pattern) => pattern.test(implementationSource))) { warnings.push(`Tool "${tool.name}" may contain Playwright-style code; WebMCP implementations run in the page.`); } if (implementationSource.includes("eval(") || implementationSource.includes("new Function")) { diff --git a/skills/webmcp-gen/scripts/generate-stagehand-example.mjs b/skills/webmcp-gen/scripts/generate-stagehand-example.mjs new file mode 100644 index 00000000..77e2c527 --- /dev/null +++ b/skills/webmcp-gen/scripts/generate-stagehand-example.mjs @@ -0,0 +1,117 @@ +#!/usr/bin/env node +import { readFile, writeFile } from "node:fs/promises"; +import path from "node:path"; + +function usage() { + return "Usage: generate-stagehand-example.mjs "; +} + +function assertObject(value, label) { + if (!value || typeof value !== "object" || Array.isArray(value)) { + throw new Error(`${label} must be an object.`); + } +} + +function assertValidManifest(manifest) { + assertObject(manifest, "Manifest"); + if (!String(manifest.url || "").trim()) throw new Error("Manifest is missing url."); + if (!Array.isArray(manifest.tools) || manifest.tools.length === 0) { + throw new Error("Manifest must contain at least one tool."); + } +} + +function serializeExpectedTools(tools) { + return tools.map((tool) => ({ + name: tool.name, + fixtureInput: tool.fixtureInput ?? {}, + })); +} + +function emitStagehandExample(manifest) { + const expectedTools = serializeExpectedTools(manifest.tools); + + return `#!/usr/bin/env node +import { fileURLToPath } from "node:url"; + +import { Stagehand } from "@browserbasehq/stagehand"; + +const TARGET_URL = ${JSON.stringify(manifest.url)}; +const WEBMCP_INIT_SCRIPT_PATH = fileURLToPath( + new URL("./webmcp.init.js", import.meta.url), +); +const EXPECTED_TOOLS = ${JSON.stringify(expectedTools, null, 2)}; + +async function main() { + const stagehand = new Stagehand({ + env: "LOCAL", + verbose: 2, + localBrowserLaunchOptions: { + args: ["--enable-features=WebMCPTesting,DevToolsWebMCPSupport"], + }, + }); + + try { + await stagehand.init(); + const page = + stagehand.context.pages()[0] ?? (await stagehand.context.newPage()); + + await page.addInitScript({ path: WEBMCP_INIT_SCRIPT_PATH }); + await page.goto(TARGET_URL, { waitUntil: "load" }); + + const registeredTools = await page.listWebMCPTools(); + console.log(\`Found \${registeredTools.length} WebMCP tools:\`); + for (const tool of registeredTools) { + console.log(\`- \${tool.name}: \${tool.description ?? "No description"}\`); + } + + for (const expectedTool of EXPECTED_TOOLS) { + const tool = registeredTools.find( + (registeredTool) => registeredTool.name === expectedTool.name, + ); + if (!tool) { + throw new Error(\`Expected WebMCP tool "\${expectedTool.name}" was not registered.\`); + } + + const invocation = await page.invokeWebMCPTool( + tool.name, + expectedTool.fixtureInput, + { frameId: tool.frameId }, + ); + const result = await invocation.result; + + console.log(\`Invocation result for \${tool.name}:\`); + console.log(JSON.stringify(result, null, 2)); + } + } finally { + await stagehand.close().catch(() => {}); + } +} + +main().catch((error) => { + console.error(error instanceof Error ? error.message : String(error)); + process.exitCode = 1; +}); +`; +} + +async function main() { + const artifactDir = process.argv[2]; + if (!artifactDir) throw new Error(usage()); + + const resolvedArtifactDir = path.resolve(process.cwd(), artifactDir); + const manifestPath = path.join(resolvedArtifactDir, "manifest.json"); + const manifest = JSON.parse(await readFile(manifestPath, "utf8")); + assertValidManifest(manifest); + + await writeFile( + path.join(resolvedArtifactDir, "stagehand-example.mjs"), + emitStagehandExample(manifest), + "utf8", + ); + console.log(`Generated Stagehand example at ${path.join(resolvedArtifactDir, "stagehand-example.mjs")}`); +} + +main().catch((error) => { + console.error(error instanceof Error ? error.message : String(error)); + process.exitCode = 1; +}); From 22f06a319642c133e832b2f047335ad7bd9ae972 Mon Sep 17 00:00:00 2001 From: Shrey Pandya Date: Thu, 11 Jun 2026 11:34:14 -0700 Subject: [PATCH 3/8] Conform webmcp-gen frontmatter to house skill standards - allowed-tools: space-separated list (matches ui-test style) - compatibility: include install commands (pnpm install, npm install -g browse) Co-Authored-By: Claude Fable 5 --- skills/webmcp-gen/SKILL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skills/webmcp-gen/SKILL.md b/skills/webmcp-gen/SKILL.md index 7a30b401..455c303a 100644 --- a/skills/webmcp-gen/SKILL.md +++ b/skills/webmcp-gen/SKILL.md @@ -1,9 +1,9 @@ --- name: webmcp-gen description: Create, compile, and validate site-specific WebMCP init scripts from a target URL and desired tool capability. Use when the user wants to author WebMCP tools for a website, produce a webmcp.init.js artifact, or test WebMCP registration and invocation through Stagehand. -compatibility: "Requires Node 18+, Chrome/Chromium with WebMCP testing flags, and the Stagehand package declared in this skill's package.json." +compatibility: "Requires Node 18+ and Chrome/Chromium with WebMCP testing flags. Run `pnpm install` in the skill directory to install the Stagehand dependency. Page exploration uses the browse CLI (`npm install -g browse`)." license: MIT -allowed-tools: Bash, Read, Grep, Edit, Write +allowed-tools: Bash Read Grep Edit Write --- # WebMCP Gen From c7bbb3517fcdaaf8326bcf0baa71639590af3cfd Mon Sep 17 00:00:00 2001 From: Shrey Pandya Date: Thu, 18 Jun 2026 10:04:46 -0700 Subject: [PATCH 4/8] fix(webmcp-gen): make validate.mjs fail on empty tools and empty errorText Address Cursor Bugbot review on validate.mjs: - Empty manifest tools array no longer reports "passed" (vacuous every() + 0===0 length check); now pushes an explicit error and requires >0 tools. - A tool returning { success: false } with an empty errorText is now stored as an error and fails validation (|| fallback instead of ?? on ""). Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/webmcp-gen/scripts/validate.mjs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/skills/webmcp-gen/scripts/validate.mjs b/skills/webmcp-gen/scripts/validate.mjs index 94a22d9b..fc1d562e 100644 --- a/skills/webmcp-gen/scripts/validate.mjs +++ b/skills/webmcp-gen/scripts/validate.mjs @@ -92,8 +92,9 @@ async function validateArtifact(artifactDir) { { frameId: foundTool.frameId } ); const result = await invocation.result; - const error = result.errorText || outputLooksFailed(result.output) - ? result.errorText ?? "Tool returned an output with success=false." + const failed = Boolean(result.errorText) || outputLooksFailed(result.output); + const error = failed + ? result.errorText || "Tool returned an output with success=false." : undefined; tools.push({ name: expectedTool.name, @@ -118,7 +119,12 @@ async function validateArtifact(artifactDir) { await stagehand.close().catch(() => {}); } + if (manifest.tools.length === 0) { + errors.push("Manifest declares no tools; nothing to validate."); + } + const status = errors.length === 0 && + manifest.tools.length > 0 && tools.length === manifest.tools.length && tools.every((tool) => tool.found && tool.invoked && tool.status === "Completed" && !tool.error) ? "passed" From 31c604cd33ed8de50985c07db0d6a131f100280c Mon Sep 17 00:00:00 2001 From: Shrey Pandya Date: Thu, 18 Jun 2026 10:05:41 -0700 Subject: [PATCH 5/8] fix(webmcp-gen): reject path-traversal in scaffold slug segments Address Cursor Bugbot: parseSlug accepted a ".." segment (e.g. "../task"), and artifactDirFor resolves with path.resolve, so scaffold could write outside the artifacts/ tree. Now each slug segment must match ^[A-Za-z0-9][A-Za-z0-9._-]*$, rejecting ".." and leading-dot segments. Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/webmcp-gen/scripts/scaffold.mjs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/skills/webmcp-gen/scripts/scaffold.mjs b/skills/webmcp-gen/scripts/scaffold.mjs index 98bb41e0..96534b0b 100644 --- a/skills/webmcp-gen/scripts/scaffold.mjs +++ b/skills/webmcp-gen/scripts/scaffold.mjs @@ -29,6 +29,13 @@ function parseSlug(slug) { if (parts.length !== 2 || !parts[0] || !parts[1]) { throw new Error(`Slug must be / with exactly one slash.\n\n${usage()}`); } + for (const part of parts) { + if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(part)) { + throw new Error( + `Invalid slug segment "${part}". Each segment must start with a letter or digit and contain only letters, digits, dot, dash, or underscore (no path traversal).\n\n${usage()}` + ); + } + } return { domain: parts[0], task: parts[1] }; } From c4b95607f56565b75a4d5db3a3968d95ffff7384 Mon Sep 17 00:00:00 2001 From: Shrey Pandya Date: Thu, 18 Jun 2026 10:11:22 -0700 Subject: [PATCH 6/8] fix(webmcp-gen): guard validate.mjs against non-array manifest tools Address Cursor Bugbot: a manifest with missing/null `tools` made `manifest.tools.length` throw after the try/finally, crashing before eval.json/eval-report.md were written. Now validate early-returns a written "failed" report when `tools` is not an array. Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/webmcp-gen/scripts/validate.mjs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/skills/webmcp-gen/scripts/validate.mjs b/skills/webmcp-gen/scripts/validate.mjs index fc1d562e..63935801 100644 --- a/skills/webmcp-gen/scripts/validate.mjs +++ b/skills/webmcp-gen/scripts/validate.mjs @@ -43,6 +43,18 @@ async function validateArtifact(artifactDir) { const errors = []; const tools = []; + if (!Array.isArray(manifest.tools)) { + const result = { + artifactDir, + url: manifest.url, + status: "failed", + tools, + errors: ["Manifest `tools` must be an array."] + }; + await writeEvalResult(artifactDir, result); + return result; + } + try { await access(scriptPath); } catch { From 031ecb954c94f716a62dc1063e13e6c21b6ec5bf Mon Sep 17 00:00:00 2001 From: Shrey Pandya Date: Thu, 18 Jun 2026 10:22:24 -0700 Subject: [PATCH 7/8] fix(webmcp-gen): cap scaffolded tool name to 80 chars, widen validate tool-list timeout Address Cursor Bugbot: - scaffold.mjs toolNameFor now slices to compile.mjs's 1-80 char limit so a long slug can't scaffold a manifest that then fails compile. - validate.mjs listWebMCPTools timeout 1000ms -> 5000ms so slow page loads don't false-report tools as unregistered (example uses the default wait). Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/webmcp-gen/scripts/scaffold.mjs | 8 +++++++- skills/webmcp-gen/scripts/validate.mjs | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/skills/webmcp-gen/scripts/scaffold.mjs b/skills/webmcp-gen/scripts/scaffold.mjs index 96534b0b..5341869a 100644 --- a/skills/webmcp-gen/scripts/scaffold.mjs +++ b/skills/webmcp-gen/scripts/scaffold.mjs @@ -44,7 +44,13 @@ function artifactDirFor(slug, outRoot) { } function toolNameFor(domain, task) { - return `${domain}_${task}`.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, ""); + // Keep within compile.mjs's 1-80 char tool-name limit so a scaffolded + // manifest never fails compile on an over-long generated name. + return `${domain}_${task}` + .replace(/[^a-zA-Z0-9]+/g, "_") + .replace(/^_+|_+$/g, "") + .slice(0, 80) + .replace(/_+$/, ""); } async function main() { diff --git a/skills/webmcp-gen/scripts/validate.mjs b/skills/webmcp-gen/scripts/validate.mjs index 63935801..895487cc 100644 --- a/skills/webmcp-gen/scripts/validate.mjs +++ b/skills/webmcp-gen/scripts/validate.mjs @@ -83,7 +83,7 @@ async function validateArtifact(artifactDir) { await page.addInitScript({ path: scriptPath }); await page.goto(manifest.url, { waitUntil: "load" }); - const registeredTools = await page.listWebMCPTools({ timeoutMs: 1000 }); + const registeredTools = await page.listWebMCPTools({ timeoutMs: 5000 }); for (const expectedTool of manifest.tools) { const foundTool = registeredTools.find((tool) => tool.name === expectedTool.name); From fa4fcc02f6160e88e2832d649a6d8b7991fd0172 Mon Sep 17 00:00:00 2001 From: Shrey Pandya Date: Thu, 18 Jun 2026 11:01:20 -0700 Subject: [PATCH 8/8] feat(webmcp-gen): emit stagehand-example as .ts run via tsx Match the create-browser-app / browserbase/templates convention (TS examples run with tsx). The generator now writes stagehand-example.ts (no shebang); package.json adds tsx/typescript/@types/node devDeps; SKILL.md documents `npx tsx stagehand-example.ts` and points to `npx create-browser-app` for turning the demo into a standalone project. Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/webmcp-gen/SKILL.md | 18 +- skills/webmcp-gen/package.json | 5 + skills/webmcp-gen/pnpm-lock.yaml | 324 +++++++++++++++++- .../scripts/generate-stagehand-example.mjs | 7 +- 4 files changed, 332 insertions(+), 22 deletions(-) diff --git a/skills/webmcp-gen/SKILL.md b/skills/webmcp-gen/SKILL.md index 455c303a..6c657b13 100644 --- a/skills/webmcp-gen/SKILL.md +++ b/skills/webmcp-gen/SKILL.md @@ -14,18 +14,15 @@ This skill does not call a nested agent. You are responsible for exploring the p ## Setup check -From the skill directory, install the Stagehand dependency if it is not already installed: +From the skill directory, install dependencies if they are not already installed: ```bash cd skills/webmcp-gen pnpm install ``` -The skill's `package.json` points at the published Stagehand package: - -```text -@browserbasehq/stagehand -``` +This installs the pinned Stagehand package plus the TypeScript toolchain (`tsx`, +`typescript`, `@types/node`) used to run the generated `stagehand-example.ts`. ## Workflow @@ -68,10 +65,11 @@ Prefer `browse snapshot`, page text, and DOM inspection over screenshots unless node scripts/compile.mjs artifacts/example.com/page-context ``` -6. Generate a runnable Stagehand example: +6. Generate a runnable Stagehand example (`stagehand-example.ts`) and run it with `tsx`: ```bash node scripts/generate-stagehand-example.mjs artifacts/example.com/page-context +npx tsx artifacts/example.com/page-context/stagehand-example.ts ``` 7. Validate: @@ -129,7 +127,11 @@ node scripts/validate.mjs artifacts/example.com/page-context artifacts/// manifest.json webmcp.init.js - stagehand-example.mjs + stagehand-example.ts eval.json eval-report.md ``` + +To turn the example into a standalone project, scaffold a Stagehand app with +`npx create-browser-app` and drop the generated `webmcp.init.js` into it (load it +with `page.addInitScript({ path: "webmcp.init.js" })`). diff --git a/skills/webmcp-gen/package.json b/skills/webmcp-gen/package.json index 635bd5fa..23a4e202 100644 --- a/skills/webmcp-gen/package.json +++ b/skills/webmcp-gen/package.json @@ -5,5 +5,10 @@ "type": "module", "dependencies": { "@browserbasehq/stagehand": "3.6.0-alpha-fd42e65bb84825bdb7341a4953472db1ff774989" + }, + "devDependencies": { + "@types/node": "^20.14.0", + "tsx": "^4.16.0", + "typescript": "^5.5.0" } } diff --git a/skills/webmcp-gen/pnpm-lock.yaml b/skills/webmcp-gen/pnpm-lock.yaml index eaad39e4..705f8c18 100644 --- a/skills/webmcp-gen/pnpm-lock.yaml +++ b/skills/webmcp-gen/pnpm-lock.yaml @@ -11,6 +11,16 @@ importers: '@browserbasehq/stagehand': specifier: 3.6.0-alpha-fd42e65bb84825bdb7341a4953472db1ff774989 version: 3.6.0-alpha-fd42e65bb84825bdb7341a4953472db1ff774989(zod@4.4.3) + devDependencies: + '@types/node': + specifier: ^20.14.0 + version: 20.19.43 + tsx: + specifier: ^4.16.0 + version: 4.22.4 + typescript: + specifier: ^5.5.0 + version: 5.9.3 packages: @@ -147,6 +157,162 @@ packages: puppeteer-core: optional: true + '@esbuild/aix-ppc64@0.28.1': + resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.28.1': + resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.28.1': + resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.28.1': + resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.28.1': + resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.28.1': + resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.28.1': + resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.28.1': + resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.28.1': + resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.28.1': + resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.28.1': + resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.28.1': + resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.28.1': + resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.28.1': + resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.28.1': + resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.28.1': + resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.28.1': + resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.28.1': + resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.28.1': + resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.28.1': + resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.28.1': + resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.28.1': + resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.28.1': + resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.28.1': + resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.28.1': + resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.28.1': + resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@google/genai@1.52.0': resolution: {integrity: sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==} engines: {node: '>=20.0.0'} @@ -246,8 +412,8 @@ packages: '@types/node@18.19.130': resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} - '@types/node@25.9.2': - resolution: {integrity: sha512-G05zqtJhcDLb8uslf5EjCxXg9G1KQxiV8OS0R26IC//Eoyitzqe8z37I7cqvnZlrlSfgocQRfSn/AHBZJJFyGw==} + '@types/node@20.19.43': + resolution: {integrity: sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==} '@types/retry@0.12.0': resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} @@ -428,6 +594,11 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} + esbuild@0.28.1: + resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + engines: {node: '>=18'} + hasBin: true + escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -510,6 +681,11 @@ packages: resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} engines: {node: '>= 0.8'} + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} @@ -903,15 +1079,25 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsx@4.22.4: + resolution: {integrity: sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==} + engines: {node: '>=18.0.0'} + hasBin: true + type-is@2.1.0: resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} engines: {node: '>= 18'} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - undici-types@7.24.6: - resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} @@ -1184,6 +1370,84 @@ snapshots: - supports-color - utf-8-validate + '@esbuild/aix-ppc64@0.28.1': + optional: true + + '@esbuild/android-arm64@0.28.1': + optional: true + + '@esbuild/android-arm@0.28.1': + optional: true + + '@esbuild/android-x64@0.28.1': + optional: true + + '@esbuild/darwin-arm64@0.28.1': + optional: true + + '@esbuild/darwin-x64@0.28.1': + optional: true + + '@esbuild/freebsd-arm64@0.28.1': + optional: true + + '@esbuild/freebsd-x64@0.28.1': + optional: true + + '@esbuild/linux-arm64@0.28.1': + optional: true + + '@esbuild/linux-arm@0.28.1': + optional: true + + '@esbuild/linux-ia32@0.28.1': + optional: true + + '@esbuild/linux-loong64@0.28.1': + optional: true + + '@esbuild/linux-mips64el@0.28.1': + optional: true + + '@esbuild/linux-ppc64@0.28.1': + optional: true + + '@esbuild/linux-riscv64@0.28.1': + optional: true + + '@esbuild/linux-s390x@0.28.1': + optional: true + + '@esbuild/linux-x64@0.28.1': + optional: true + + '@esbuild/netbsd-arm64@0.28.1': + optional: true + + '@esbuild/netbsd-x64@0.28.1': + optional: true + + '@esbuild/openbsd-arm64@0.28.1': + optional: true + + '@esbuild/openbsd-x64@0.28.1': + optional: true + + '@esbuild/openharmony-arm64@0.28.1': + optional: true + + '@esbuild/sunos-x64@0.28.1': + optional: true + + '@esbuild/win32-arm64@0.28.1': + optional: true + + '@esbuild/win32-ia32@0.28.1': + optional: true + + '@esbuild/win32-x64@0.28.1': + optional: true + '@google/genai@1.52.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(bufferutil@4.1.0)': dependencies: google-auth-library: 10.7.0 @@ -1294,16 +1558,16 @@ snapshots: '@types/node-fetch@2.6.13': dependencies: - '@types/node': 18.19.130 + '@types/node': 20.19.43 form-data: 4.0.5 '@types/node@18.19.130': dependencies: undici-types: 5.26.5 - '@types/node@25.9.2': + '@types/node@20.19.43': dependencies: - undici-types: 7.24.6 + undici-types: 6.21.0 '@types/retry@0.12.0': {} @@ -1389,7 +1653,7 @@ snapshots: chrome-launcher@1.2.1: dependencies: - '@types/node': 25.9.2 + '@types/node': 20.19.43 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 2.0.2 @@ -1471,6 +1735,35 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.4 + esbuild@0.28.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.1 + '@esbuild/android-arm': 0.28.1 + '@esbuild/android-arm64': 0.28.1 + '@esbuild/android-x64': 0.28.1 + '@esbuild/darwin-arm64': 0.28.1 + '@esbuild/darwin-x64': 0.28.1 + '@esbuild/freebsd-arm64': 0.28.1 + '@esbuild/freebsd-x64': 0.28.1 + '@esbuild/linux-arm': 0.28.1 + '@esbuild/linux-arm64': 0.28.1 + '@esbuild/linux-ia32': 0.28.1 + '@esbuild/linux-loong64': 0.28.1 + '@esbuild/linux-mips64el': 0.28.1 + '@esbuild/linux-ppc64': 0.28.1 + '@esbuild/linux-riscv64': 0.28.1 + '@esbuild/linux-s390x': 0.28.1 + '@esbuild/linux-x64': 0.28.1 + '@esbuild/netbsd-arm64': 0.28.1 + '@esbuild/netbsd-x64': 0.28.1 + '@esbuild/openbsd-arm64': 0.28.1 + '@esbuild/openbsd-x64': 0.28.1 + '@esbuild/openharmony-arm64': 0.28.1 + '@esbuild/sunos-x64': 0.28.1 + '@esbuild/win32-arm64': 0.28.1 + '@esbuild/win32-ia32': 0.28.1 + '@esbuild/win32-x64': 0.28.1 + escape-html@1.0.3: {} escape-string-regexp@4.0.0: @@ -1578,6 +1871,9 @@ snapshots: fresh@2.0.0: {} + fsevents@2.3.3: + optional: true + function-bind@1.1.2: {} gaxios@7.1.5: @@ -1864,7 +2160,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.1 - '@types/node': 25.9.2 + '@types/node': 20.19.43 long: 5.3.2 proxy-addr@2.0.7: @@ -2010,15 +2306,23 @@ snapshots: tslib@2.8.1: optional: true + tsx@4.22.4: + dependencies: + esbuild: 0.28.1 + optionalDependencies: + fsevents: 2.3.3 + type-is@2.1.0: dependencies: content-type: 2.0.0 media-typer: 1.1.0 mime-types: 3.0.2 + typescript@5.9.3: {} + undici-types@5.26.5: {} - undici-types@7.24.6: {} + undici-types@6.21.0: {} unpipe@1.0.0: {} diff --git a/skills/webmcp-gen/scripts/generate-stagehand-example.mjs b/skills/webmcp-gen/scripts/generate-stagehand-example.mjs index 77e2c527..64774c32 100644 --- a/skills/webmcp-gen/scripts/generate-stagehand-example.mjs +++ b/skills/webmcp-gen/scripts/generate-stagehand-example.mjs @@ -30,8 +30,7 @@ function serializeExpectedTools(tools) { function emitStagehandExample(manifest) { const expectedTools = serializeExpectedTools(manifest.tools); - return `#!/usr/bin/env node -import { fileURLToPath } from "node:url"; + return `import { fileURLToPath } from "node:url"; import { Stagehand } from "@browserbasehq/stagehand"; @@ -104,11 +103,11 @@ async function main() { assertValidManifest(manifest); await writeFile( - path.join(resolvedArtifactDir, "stagehand-example.mjs"), + path.join(resolvedArtifactDir, "stagehand-example.ts"), emitStagehandExample(manifest), "utf8", ); - console.log(`Generated Stagehand example at ${path.join(resolvedArtifactDir, "stagehand-example.mjs")}`); + console.log(`Generated Stagehand example at ${path.join(resolvedArtifactDir, "stagehand-example.ts")}`); } main().catch((error) => {