From 4b61b2c7e29180d569d8b4200ebcfaa2d6e29259 Mon Sep 17 00:00:00 2001 From: lforst <8118419+lforst@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:39:11 +0000 Subject: [PATCH 1/3] feat: Add `@cloudflare/think` instrumentation --- .../cloudflare-think-instrumentation.md | 5 + e2e/config/pr-comment-scenarios.json | 15 + .../cloudflare-think-v0-auto.cassette.json | 651 +++ ...udflare-think-v0-latest-auto.cassette.json | 651 +++ ...flare-think-v0-latest-manual.cassette.json | 651 +++ .../cloudflare-think-v0-manual.cassette.json | 651 +++ .../cloudflare-think-v0-auto.span-tree.json | 79 + .../cloudflare-think-v0-auto.span-tree.txt | 59 + ...dflare-think-v0-latest-auto.span-tree.json | 79 + ...udflare-think-v0-latest-auto.span-tree.txt | 59 + ...lare-think-v0-latest-manual.span-tree.json | 79 + ...flare-think-v0-latest-manual.span-tree.txt | 59 + .../cloudflare-think-v0-manual.span-tree.json | 79 + .../cloudflare-think-v0-manual.span-tree.txt | 59 + .../assertions.ts | 187 + .../cassette-filter.mjs | 13 + .../package.json | 28 + .../pnpm-lock.yaml | 4925 +++++++++++++++++ .../scenario.test.ts | 68 + .../scenario.ts | 97 + .../src/worker.ts | 89 + .../src/wrapped-ai.ts | 8 + .../vite.config.ts | 31 + .../wrangler.jsonc | 21 + .../auto-instrumentations/bundler/plugin.ts | 23 +- js/src/auto-instrumentations/bundler/vite.ts | 37 +- .../bundler/webpack-loader.ts | 4 +- js/src/auto-instrumentations/configs/all.ts | 5 + .../configs/cloudflare-think.test.ts | 34 + .../configs/cloudflare-think.ts | 20 + js/src/auto-instrumentations/index.ts | 1 + js/src/exports.ts | 1 + .../instrumentation/braintrust-plugin.test.ts | 27 + js/src/instrumentation/braintrust-plugin.ts | 12 + js/src/instrumentation/config.ts | 3 + .../instrumentation/plugins/ai-sdk-plugin.ts | 79 +- .../plugins/cloudflare-think-channels.ts | 22 + .../plugins/cloudflare-think-context.ts | 32 + .../plugins/cloudflare-think-plugin.test.ts | 158 + .../plugins/cloudflare-think-plugin.ts | 373 ++ js/src/vendor-sdk-types/cloudflare-think.ts | 31 + js/src/wrappers/cloudflare-think.test.ts | 91 + js/src/wrappers/cloudflare-think.ts | 75 + 43 files changed, 9660 insertions(+), 11 deletions(-) create mode 100644 .changeset/cloudflare-think-instrumentation.md create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-auto.cassette.json create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-latest-auto.cassette.json create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-latest-manual.cassette.json create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-manual.cassette.json create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-auto.span-tree.json create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-auto.span-tree.txt create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-auto.span-tree.json create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-auto.span-tree.txt create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-manual.span-tree.json create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-manual.span-tree.txt create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-manual.span-tree.json create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-manual.span-tree.txt create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/assertions.ts create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/cassette-filter.mjs create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/package.json create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/pnpm-lock.yaml create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/scenario.test.ts create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/scenario.ts create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/src/worker.ts create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/src/wrapped-ai.ts create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/vite.config.ts create mode 100644 e2e/scenarios/cloudflare-think-instrumentation/wrangler.jsonc create mode 100644 js/src/auto-instrumentations/configs/cloudflare-think.test.ts create mode 100644 js/src/auto-instrumentations/configs/cloudflare-think.ts create mode 100644 js/src/instrumentation/plugins/cloudflare-think-channels.ts create mode 100644 js/src/instrumentation/plugins/cloudflare-think-context.ts create mode 100644 js/src/instrumentation/plugins/cloudflare-think-plugin.test.ts create mode 100644 js/src/instrumentation/plugins/cloudflare-think-plugin.ts create mode 100644 js/src/vendor-sdk-types/cloudflare-think.ts create mode 100644 js/src/wrappers/cloudflare-think.test.ts create mode 100644 js/src/wrappers/cloudflare-think.ts diff --git a/.changeset/cloudflare-think-instrumentation.md b/.changeset/cloudflare-think-instrumentation.md new file mode 100644 index 000000000..828af7f7e --- /dev/null +++ b/.changeset/cloudflare-think-instrumentation.md @@ -0,0 +1,5 @@ +--- +"braintrust": minor +--- + +feat: Add `@cloudflare/think` instrumentation diff --git a/e2e/config/pr-comment-scenarios.json b/e2e/config/pr-comment-scenarios.json index a644fd45d..9059b337a 100644 --- a/e2e/config/pr-comment-scenarios.json +++ b/e2e/config/pr-comment-scenarios.json @@ -83,6 +83,21 @@ } ] }, + { + "scenarioDirName": "cloudflare-think-instrumentation", + "label": "Cloudflare Think Instrumentation", + "metadataScenario": "cloudflare-think-instrumentation", + "variants": [ + { + "variantKey": "cloudflare-think-v0", + "label": "v0.13 pinned" + }, + { + "variantKey": "cloudflare-think-v0-latest", + "label": "v0.13 latest" + } + ] + }, { "scenarioDirName": "openai-agents-instrumentation", "label": "OpenAI Agents Instrumentation", diff --git a/e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-auto.cassette.json b/e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-auto.cassette.json new file mode 100644 index 000000000..d3cdd11db --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-auto.cassette.json @@ -0,0 +1,651 @@ +{ + "entries": [ + { + "callIndex": 0, + "id": "02bfffc5f7e45fcc", + "matchKey": "POST api.openai.com/v1/chat/completions", + "recordedAt": "2026-07-20T14:51:54.374Z", + "request": { + "body": { + "kind": "json", + "value": { + "messages": [ + { + "content": "You are a deterministic weather-test agent. You must call lookup_weather exactly once with Vienna before answering. After the tool result, reply with exactly: \"Vienna is sunny and 21°C.\"\n\nYou are running inside a Think agent.\n\nCapabilities available in this turn:\n- You can inspect and edit the agent workspace using the available file tools.\n- Use the tools exposed in this turn when they materially improve accuracy or let you act on the user's request. Treat tool descriptions and schemas as the source of truth.\n- Some tools may call server code, browser/client code, MCP servers, extensions, or delegated agents. Use them according to their descriptions.\n- Do not claim access to capabilities that are not exposed as tools in this turn.", + "role": "developer" + }, + { + "content": "What is the weather in Vienna?", + "role": "user" + } + ], + "model": "gpt-5-nano", + "stream": true, + "stream_options": { + "include_usage": true + }, + "tool_choice": "auto", + "tools": [ + { + "function": { + "description": "Read a workspace file. Text files return line-numbered content. Images and PDFs are passed to capable models as file content. Use offset and limit for large text files. Returns null if the file does not exist.", + "name": "read", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Number of lines to read", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "1-indexed line number to start reading from", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Write content to a file. Creates the file if it does not exist, overwrites if it does. Parent directories are created automatically.", + "name": "write", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Make a targeted edit to a file by replacing an exact string match. Provide the old_string to find and new_string to replace it with. The old_string must match exactly (including whitespace and indentation). Use an empty old_string with new_string to create a new file.", + "name": "edit", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "new_string": { + "description": "Replacement text", + "type": "string" + }, + "old_string": { + "description": "Exact text to find and replace. Empty string to create a new file.", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "old_string", "new_string"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "List files and directories in a given path. Returns names, types, and sizes for each entry.", + "name": "list", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Maximum number of entries to return (default: 200)", + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "Number of entries to skip (for pagination)", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "path": { + "default": "/", + "description": "Absolute path to the directory to list", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Find files matching a glob pattern. Supports standard glob syntax: * matches any file, ** matches directories recursively, ? matches a single character. Returns matching file paths with types and sizes.", + "name": "find", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "pattern": { + "description": "Glob pattern to match (e.g. \"**/*.ts\", \"src/**/*.test.ts\", \"*.md\")", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Search file contents using a regular expression or fixed string. Returns matching lines with file paths and line numbers. Searches all files matching the include glob, or all files if not specified.", + "name": "grep", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "caseSensitive": { + "description": "If true, search is case-sensitive (default: false)", + "type": "boolean" + }, + "contextLines": { + "description": "Number of context lines around each match (default: 0)", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "fixedString": { + "description": "If true, treat query as a literal string instead of regex", + "type": "boolean" + }, + "include": { + "description": "Glob pattern to filter files (e.g. \"**/*.ts\"). Defaults to \"**/*\"", + "type": "string" + }, + "query": { + "description": "Search pattern (regex or fixed string)", + "type": "string" + } + }, + "required": ["query"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Delete a file or directory. Set recursive to true to remove non-empty directories.", + "name": "delete", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "path": { + "description": "Absolute path to the file or directory", + "type": "string" + }, + "recursive": { + "description": "If true, remove directories and their contents recursively", + "type": "boolean" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Run a Bash script against the workspace. Use for shell-style workflows that combine multiple file operations. The script runs in a sandboxed virtual filesystem with the workspace mounted at `/` (also the default working directory) — there is no `/workspace` or `/home`; use absolute paths like `/notes.txt`. Changed files are written back to the workspace.", + "name": "bash", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "cwd": { + "description": "Working directory for the script. Defaults to / (the workspace root)", + "type": "string" + }, + "script": { + "description": "Bash script to run", + "type": "string" + } + }, + "required": ["script"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Get deterministic weather for a city.", + "name": "lookup_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "city": { + "type": "string" + } + }, + "required": ["city"], + "type": "object" + } + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/chat/completions" + }, + "response": { + "body": { + "chunks": [ + "data: {\"id\":\"chatcmpl-E3jdQGseZWQcLrsgw93VodLi706J2\",\"object\":\"chat.completion.chunk\",\"created\":1784559112,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"id\":\"call_WAf5AUNeoomo5nRHZF05YYu2\",\"type\":\"function\",\"function\":{\"name\":\"lookup_weather\",\"arguments\":\"\"}}],\"refusal\":null},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"2tovhZz8nyIwA\"}", + "data: {\"id\":\"chatcmpl-E3jdQGseZWQcLrsgw93VodLi706J2\",\"object\":\"chat.completion.chunk\",\"created\":1784559112,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"{\\\"\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"bhRfQYMY6V\"}", + "data: {\"id\":\"chatcmpl-E3jdQGseZWQcLrsgw93VodLi706J2\",\"object\":\"chat.completion.chunk\",\"created\":1784559112,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"city\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"H1W1zAIpR\"}", + "data: {\"id\":\"chatcmpl-E3jdQGseZWQcLrsgw93VodLi706J2\",\"object\":\"chat.completion.chunk\",\"created\":1784559112,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\":\\\"\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"d0JvUwDa\"}", + "data: {\"id\":\"chatcmpl-E3jdQGseZWQcLrsgw93VodLi706J2\",\"object\":\"chat.completion.chunk\",\"created\":1784559112,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"Vien\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"OuxQlPCsx\"}", + "data: {\"id\":\"chatcmpl-E3jdQGseZWQcLrsgw93VodLi706J2\",\"object\":\"chat.completion.chunk\",\"created\":1784559112,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"na\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"7I4BXwqVstQ\"}", + "data: {\"id\":\"chatcmpl-E3jdQGseZWQcLrsgw93VodLi706J2\",\"object\":\"chat.completion.chunk\",\"created\":1784559112,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\"}\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"UsygssD4Cd\"}", + "data: {\"id\":\"chatcmpl-E3jdQGseZWQcLrsgw93VodLi706J2\",\"object\":\"chat.completion.chunk\",\"created\":1784559112,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"tool_calls\"}],\"usage\":null,\"obfuscation\":\"5txPBCycfCU\"}", + "data: {\"id\":\"chatcmpl-E3jdQGseZWQcLrsgw93VodLi706J2\",\"object\":\"chat.completion.chunk\",\"created\":1784559112,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[],\"usage\":{\"prompt_tokens\":1042,\"completion_tokens\":152,\"total_tokens\":1194,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":128,\"audio_tokens\":0,\"accepted_prediction_tokens\":0,\"rejected_prediction_tokens\":0}},\"obfuscation\":\"yjX19p3lyT8GxQV\"}", + "data: [DONE]" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a1e2c9562ffd5ca1-IAD", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 20 Jul 2026 14:51:54 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "1576", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "30000", + "x-ratelimit-limit-tokens": "180000000", + "x-ratelimit-remaining-requests": "29999", + "x-ratelimit-remaining-tokens": "179999805", + "x-ratelimit-reset-requests": "2ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_824c4d66b14b401a80bf8e6ac6dfb030" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 1, + "id": "72f5fa1797c84800", + "matchKey": "POST api.openai.com/v1/chat/completions", + "recordedAt": "2026-07-20T14:51:56.394Z", + "request": { + "body": { + "kind": "json", + "value": { + "messages": [ + { + "content": "You are a deterministic weather-test agent. You must call lookup_weather exactly once with Vienna before answering. After the tool result, reply with exactly: \"Vienna is sunny and 21°C.\"\n\nYou are running inside a Think agent.\n\nCapabilities available in this turn:\n- You can inspect and edit the agent workspace using the available file tools.\n- Use the tools exposed in this turn when they materially improve accuracy or let you act on the user's request. Treat tool descriptions and schemas as the source of truth.\n- Some tools may call server code, browser/client code, MCP servers, extensions, or delegated agents. Use them according to their descriptions.\n- Do not claim access to capabilities that are not exposed as tools in this turn.", + "role": "developer" + }, + { + "content": "What is the weather in Vienna?", + "role": "user" + }, + { + "content": null, + "role": "assistant", + "tool_calls": [ + { + "function": { + "arguments": "{\"city\":\"Vienna\"}", + "name": "lookup_weather" + }, + "id": "call_WAf5AUNeoomo5nRHZF05YYu2", + "type": "function" + } + ] + }, + { + "content": "{\"city\":\"Vienna\",\"condition\":\"sunny\",\"degreesC\":21}", + "role": "tool", + "tool_call_id": "call_WAf5AUNeoomo5nRHZF05YYu2" + } + ], + "model": "gpt-5-nano", + "stream": true, + "stream_options": { + "include_usage": true + }, + "tool_choice": "auto", + "tools": [ + { + "function": { + "description": "Read a workspace file. Text files return line-numbered content. Images and PDFs are passed to capable models as file content. Use offset and limit for large text files. Returns null if the file does not exist.", + "name": "read", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Number of lines to read", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "1-indexed line number to start reading from", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Write content to a file. Creates the file if it does not exist, overwrites if it does. Parent directories are created automatically.", + "name": "write", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Make a targeted edit to a file by replacing an exact string match. Provide the old_string to find and new_string to replace it with. The old_string must match exactly (including whitespace and indentation). Use an empty old_string with new_string to create a new file.", + "name": "edit", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "new_string": { + "description": "Replacement text", + "type": "string" + }, + "old_string": { + "description": "Exact text to find and replace. Empty string to create a new file.", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "old_string", "new_string"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "List files and directories in a given path. Returns names, types, and sizes for each entry.", + "name": "list", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Maximum number of entries to return (default: 200)", + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "Number of entries to skip (for pagination)", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "path": { + "default": "/", + "description": "Absolute path to the directory to list", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Find files matching a glob pattern. Supports standard glob syntax: * matches any file, ** matches directories recursively, ? matches a single character. Returns matching file paths with types and sizes.", + "name": "find", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "pattern": { + "description": "Glob pattern to match (e.g. \"**/*.ts\", \"src/**/*.test.ts\", \"*.md\")", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Search file contents using a regular expression or fixed string. Returns matching lines with file paths and line numbers. Searches all files matching the include glob, or all files if not specified.", + "name": "grep", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "caseSensitive": { + "description": "If true, search is case-sensitive (default: false)", + "type": "boolean" + }, + "contextLines": { + "description": "Number of context lines around each match (default: 0)", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "fixedString": { + "description": "If true, treat query as a literal string instead of regex", + "type": "boolean" + }, + "include": { + "description": "Glob pattern to filter files (e.g. \"**/*.ts\"). Defaults to \"**/*\"", + "type": "string" + }, + "query": { + "description": "Search pattern (regex or fixed string)", + "type": "string" + } + }, + "required": ["query"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Delete a file or directory. Set recursive to true to remove non-empty directories.", + "name": "delete", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "path": { + "description": "Absolute path to the file or directory", + "type": "string" + }, + "recursive": { + "description": "If true, remove directories and their contents recursively", + "type": "boolean" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Run a Bash script against the workspace. Use for shell-style workflows that combine multiple file operations. The script runs in a sandboxed virtual filesystem with the workspace mounted at `/` (also the default working directory) — there is no `/workspace` or `/home`; use absolute paths like `/notes.txt`. Changed files are written back to the workspace.", + "name": "bash", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "cwd": { + "description": "Working directory for the script. Defaults to / (the workspace root)", + "type": "string" + }, + "script": { + "description": "Bash script to run", + "type": "string" + } + }, + "required": ["script"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Get deterministic weather for a city.", + "name": "lookup_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "city": { + "type": "string" + } + }, + "required": ["city"], + "type": "object" + } + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/chat/completions" + }, + "response": { + "body": { + "chunks": [ + "data: {\"id\":\"chatcmpl-E3jdSfRhSJA2nOXT8Icbjcjtz0K1x\",\"object\":\"chat.completion.chunk\",\"created\":1784559114,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"refusal\":null},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"7ixbG\"}", + "data: {\"id\":\"chatcmpl-E3jdSfRhSJA2nOXT8Icbjcjtz0K1x\",\"object\":\"chat.completion.chunk\",\"created\":1784559114,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"Vien\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"kfD\"}", + "data: {\"id\":\"chatcmpl-E3jdSfRhSJA2nOXT8Icbjcjtz0K1x\",\"object\":\"chat.completion.chunk\",\"created\":1784559114,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"na\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"1aym5\"}", + "data: {\"id\":\"chatcmpl-E3jdSfRhSJA2nOXT8Icbjcjtz0K1x\",\"object\":\"chat.completion.chunk\",\"created\":1784559114,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" is\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"oDEn\"}", + "data: {\"id\":\"chatcmpl-E3jdSfRhSJA2nOXT8Icbjcjtz0K1x\",\"object\":\"chat.completion.chunk\",\"created\":1784559114,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" sunny\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"X\"}", + "data: {\"id\":\"chatcmpl-E3jdSfRhSJA2nOXT8Icbjcjtz0K1x\",\"object\":\"chat.completion.chunk\",\"created\":1784559114,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" and\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"8V7\"}", + "data: {\"id\":\"chatcmpl-E3jdSfRhSJA2nOXT8Icbjcjtz0K1x\",\"object\":\"chat.completion.chunk\",\"created\":1784559114,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"LWoXnc\"}", + "data: {\"id\":\"chatcmpl-E3jdSfRhSJA2nOXT8Icbjcjtz0K1x\",\"object\":\"chat.completion.chunk\",\"created\":1784559114,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"21\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"DbemJ\"}", + "data: {\"id\":\"chatcmpl-E3jdSfRhSJA2nOXT8Icbjcjtz0K1x\",\"object\":\"chat.completion.chunk\",\"created\":1784559114,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"°C\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"Fz0ek\"}", + "data: {\"id\":\"chatcmpl-E3jdSfRhSJA2nOXT8Icbjcjtz0K1x\",\"object\":\"chat.completion.chunk\",\"created\":1784559114,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\".\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"3ygAlq\"}", + "data: {\"id\":\"chatcmpl-E3jdSfRhSJA2nOXT8Icbjcjtz0K1x\",\"object\":\"chat.completion.chunk\",\"created\":1784559114,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}],\"usage\":null,\"obfuscation\":\"X\"}", + "data: {\"id\":\"chatcmpl-E3jdSfRhSJA2nOXT8Icbjcjtz0K1x\",\"object\":\"chat.completion.chunk\",\"created\":1784559114,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[],\"usage\":{\"prompt_tokens\":1087,\"completion_tokens\":147,\"total_tokens\":1234,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":128,\"audio_tokens\":0,\"accepted_prediction_tokens\":0,\"rejected_prediction_tokens\":0}},\"obfuscation\":\"fz7bIoP9tJSm74p\"}", + "data: [DONE]" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a1e2c9612b495ca1-IAD", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 20 Jul 2026 14:51:56 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "1812", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "30000", + "x-ratelimit-limit-tokens": "180000000", + "x-ratelimit-remaining-requests": "29999", + "x-ratelimit-remaining-tokens": "179999790", + "x-ratelimit-reset-requests": "2ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_996dbc4535f44a298b86d81bcc75f03f" + }, + "status": 200, + "statusText": "OK" + } + } + ], + "meta": { + "createdAt": "2026-07-20T14:51:56.619Z" + } +} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-latest-auto.cassette.json b/e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-latest-auto.cassette.json new file mode 100644 index 000000000..30afe71bd --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-latest-auto.cassette.json @@ -0,0 +1,651 @@ +{ + "entries": [ + { + "callIndex": 0, + "id": "02bfffc5f7e45fcc", + "matchKey": "POST api.openai.com/v1/chat/completions", + "recordedAt": "2026-07-20T14:52:25.812Z", + "request": { + "body": { + "kind": "json", + "value": { + "messages": [ + { + "content": "You are a deterministic weather-test agent. You must call lookup_weather exactly once with Vienna before answering. After the tool result, reply with exactly: \"Vienna is sunny and 21°C.\"\n\nYou are running inside a Think agent.\n\nCapabilities available in this turn:\n- You can inspect and edit the agent workspace using the available file tools.\n- Use the tools exposed in this turn when they materially improve accuracy or let you act on the user's request. Treat tool descriptions and schemas as the source of truth.\n- Some tools may call server code, browser/client code, MCP servers, extensions, or delegated agents. Use them according to their descriptions.\n- Do not claim access to capabilities that are not exposed as tools in this turn.", + "role": "developer" + }, + { + "content": "What is the weather in Vienna?", + "role": "user" + } + ], + "model": "gpt-5-nano", + "stream": true, + "stream_options": { + "include_usage": true + }, + "tool_choice": "auto", + "tools": [ + { + "function": { + "description": "Read a workspace file. Text files return line-numbered content. Images and PDFs are passed to capable models as file content. Use offset and limit for large text files. Returns null if the file does not exist.", + "name": "read", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Number of lines to read", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "1-indexed line number to start reading from", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Write content to a file. Creates the file if it does not exist, overwrites if it does. Parent directories are created automatically.", + "name": "write", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Make a targeted edit to a file by replacing an exact string match. Provide the old_string to find and new_string to replace it with. The old_string must match exactly (including whitespace and indentation). Use an empty old_string with new_string to create a new file.", + "name": "edit", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "new_string": { + "description": "Replacement text", + "type": "string" + }, + "old_string": { + "description": "Exact text to find and replace. Empty string to create a new file.", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "old_string", "new_string"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "List files and directories in a given path. Returns names, types, and sizes for each entry.", + "name": "list", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Maximum number of entries to return (default: 200)", + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "Number of entries to skip (for pagination)", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "path": { + "default": "/", + "description": "Absolute path to the directory to list", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Find files matching a glob pattern. Supports standard glob syntax: * matches any file, ** matches directories recursively, ? matches a single character. Returns matching file paths with types and sizes.", + "name": "find", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "pattern": { + "description": "Glob pattern to match (e.g. \"**/*.ts\", \"src/**/*.test.ts\", \"*.md\")", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Search file contents using a regular expression or fixed string. Returns matching lines with file paths and line numbers. Searches all files matching the include glob, or all files if not specified.", + "name": "grep", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "caseSensitive": { + "description": "If true, search is case-sensitive (default: false)", + "type": "boolean" + }, + "contextLines": { + "description": "Number of context lines around each match (default: 0)", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "fixedString": { + "description": "If true, treat query as a literal string instead of regex", + "type": "boolean" + }, + "include": { + "description": "Glob pattern to filter files (e.g. \"**/*.ts\"). Defaults to \"**/*\"", + "type": "string" + }, + "query": { + "description": "Search pattern (regex or fixed string)", + "type": "string" + } + }, + "required": ["query"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Delete a file or directory. Set recursive to true to remove non-empty directories.", + "name": "delete", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "path": { + "description": "Absolute path to the file or directory", + "type": "string" + }, + "recursive": { + "description": "If true, remove directories and their contents recursively", + "type": "boolean" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Run a Bash script against the workspace. Use for shell-style workflows that combine multiple file operations. The script runs in a sandboxed virtual filesystem with the workspace mounted at `/` (also the default working directory) — there is no `/workspace` or `/home`; use absolute paths like `/notes.txt`. Changed files are written back to the workspace.", + "name": "bash", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "cwd": { + "description": "Working directory for the script. Defaults to / (the workspace root)", + "type": "string" + }, + "script": { + "description": "Bash script to run", + "type": "string" + } + }, + "required": ["script"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Get deterministic weather for a city.", + "name": "lookup_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "city": { + "type": "string" + } + }, + "required": ["city"], + "type": "object" + } + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/chat/completions" + }, + "response": { + "body": { + "chunks": [ + "data: {\"id\":\"chatcmpl-E3jduJXxphNYFI8ZkrTbQ6VKN5lff\",\"object\":\"chat.completion.chunk\",\"created\":1784559142,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"id\":\"call_mhXleGKtQKxBEaZl2TwAWENj\",\"type\":\"function\",\"function\":{\"name\":\"lookup_weather\",\"arguments\":\"\"}}],\"refusal\":null},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"4TXwvdIx9VfYx\"}", + "data: {\"id\":\"chatcmpl-E3jduJXxphNYFI8ZkrTbQ6VKN5lff\",\"object\":\"chat.completion.chunk\",\"created\":1784559142,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"{\\\"\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"qlHiC2THID\"}", + "data: {\"id\":\"chatcmpl-E3jduJXxphNYFI8ZkrTbQ6VKN5lff\",\"object\":\"chat.completion.chunk\",\"created\":1784559142,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"city\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"5M5GoS9lm\"}", + "data: {\"id\":\"chatcmpl-E3jduJXxphNYFI8ZkrTbQ6VKN5lff\",\"object\":\"chat.completion.chunk\",\"created\":1784559142,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\":\\\"\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"2xJ4ndtW\"}", + "data: {\"id\":\"chatcmpl-E3jduJXxphNYFI8ZkrTbQ6VKN5lff\",\"object\":\"chat.completion.chunk\",\"created\":1784559142,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"Vien\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"rDH9woasL\"}", + "data: {\"id\":\"chatcmpl-E3jduJXxphNYFI8ZkrTbQ6VKN5lff\",\"object\":\"chat.completion.chunk\",\"created\":1784559142,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"na\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"AC8ALlnw4HI\"}", + "data: {\"id\":\"chatcmpl-E3jduJXxphNYFI8ZkrTbQ6VKN5lff\",\"object\":\"chat.completion.chunk\",\"created\":1784559142,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\"}\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"8CAXmNORTN\"}", + "data: {\"id\":\"chatcmpl-E3jduJXxphNYFI8ZkrTbQ6VKN5lff\",\"object\":\"chat.completion.chunk\",\"created\":1784559142,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"tool_calls\"}],\"usage\":null,\"obfuscation\":\"P7HS088Q2UB\"}", + "data: {\"id\":\"chatcmpl-E3jduJXxphNYFI8ZkrTbQ6VKN5lff\",\"object\":\"chat.completion.chunk\",\"created\":1784559142,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[],\"usage\":{\"prompt_tokens\":1042,\"completion_tokens\":344,\"total_tokens\":1386,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":320,\"audio_tokens\":0,\"accepted_prediction_tokens\":0,\"rejected_prediction_tokens\":0}},\"obfuscation\":\"ceow5M8GXDtGmr9\"}", + "data: [DONE]" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a1e2ca0d1abec946-IAD", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 20 Jul 2026 14:52:25 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "3758", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "30000", + "x-ratelimit-limit-tokens": "180000000", + "x-ratelimit-remaining-requests": "29999", + "x-ratelimit-remaining-tokens": "179999805", + "x-ratelimit-reset-requests": "2ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_2c7552a5eac94a7586babe88829e6a64" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 1, + "id": "9076672dec69b810", + "matchKey": "POST api.openai.com/v1/chat/completions", + "recordedAt": "2026-07-20T14:52:27.896Z", + "request": { + "body": { + "kind": "json", + "value": { + "messages": [ + { + "content": "You are a deterministic weather-test agent. You must call lookup_weather exactly once with Vienna before answering. After the tool result, reply with exactly: \"Vienna is sunny and 21°C.\"\n\nYou are running inside a Think agent.\n\nCapabilities available in this turn:\n- You can inspect and edit the agent workspace using the available file tools.\n- Use the tools exposed in this turn when they materially improve accuracy or let you act on the user's request. Treat tool descriptions and schemas as the source of truth.\n- Some tools may call server code, browser/client code, MCP servers, extensions, or delegated agents. Use them according to their descriptions.\n- Do not claim access to capabilities that are not exposed as tools in this turn.", + "role": "developer" + }, + { + "content": "What is the weather in Vienna?", + "role": "user" + }, + { + "content": null, + "role": "assistant", + "tool_calls": [ + { + "function": { + "arguments": "{\"city\":\"Vienna\"}", + "name": "lookup_weather" + }, + "id": "call_mhXleGKtQKxBEaZl2TwAWENj", + "type": "function" + } + ] + }, + { + "content": "{\"city\":\"Vienna\",\"condition\":\"sunny\",\"degreesC\":21}", + "role": "tool", + "tool_call_id": "call_mhXleGKtQKxBEaZl2TwAWENj" + } + ], + "model": "gpt-5-nano", + "stream": true, + "stream_options": { + "include_usage": true + }, + "tool_choice": "auto", + "tools": [ + { + "function": { + "description": "Read a workspace file. Text files return line-numbered content. Images and PDFs are passed to capable models as file content. Use offset and limit for large text files. Returns null if the file does not exist.", + "name": "read", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Number of lines to read", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "1-indexed line number to start reading from", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Write content to a file. Creates the file if it does not exist, overwrites if it does. Parent directories are created automatically.", + "name": "write", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Make a targeted edit to a file by replacing an exact string match. Provide the old_string to find and new_string to replace it with. The old_string must match exactly (including whitespace and indentation). Use an empty old_string with new_string to create a new file.", + "name": "edit", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "new_string": { + "description": "Replacement text", + "type": "string" + }, + "old_string": { + "description": "Exact text to find and replace. Empty string to create a new file.", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "old_string", "new_string"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "List files and directories in a given path. Returns names, types, and sizes for each entry.", + "name": "list", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Maximum number of entries to return (default: 200)", + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "Number of entries to skip (for pagination)", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "path": { + "default": "/", + "description": "Absolute path to the directory to list", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Find files matching a glob pattern. Supports standard glob syntax: * matches any file, ** matches directories recursively, ? matches a single character. Returns matching file paths with types and sizes.", + "name": "find", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "pattern": { + "description": "Glob pattern to match (e.g. \"**/*.ts\", \"src/**/*.test.ts\", \"*.md\")", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Search file contents using a regular expression or fixed string. Returns matching lines with file paths and line numbers. Searches all files matching the include glob, or all files if not specified.", + "name": "grep", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "caseSensitive": { + "description": "If true, search is case-sensitive (default: false)", + "type": "boolean" + }, + "contextLines": { + "description": "Number of context lines around each match (default: 0)", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "fixedString": { + "description": "If true, treat query as a literal string instead of regex", + "type": "boolean" + }, + "include": { + "description": "Glob pattern to filter files (e.g. \"**/*.ts\"). Defaults to \"**/*\"", + "type": "string" + }, + "query": { + "description": "Search pattern (regex or fixed string)", + "type": "string" + } + }, + "required": ["query"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Delete a file or directory. Set recursive to true to remove non-empty directories.", + "name": "delete", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "path": { + "description": "Absolute path to the file or directory", + "type": "string" + }, + "recursive": { + "description": "If true, remove directories and their contents recursively", + "type": "boolean" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Run a Bash script against the workspace. Use for shell-style workflows that combine multiple file operations. The script runs in a sandboxed virtual filesystem with the workspace mounted at `/` (also the default working directory) — there is no `/workspace` or `/home`; use absolute paths like `/notes.txt`. Changed files are written back to the workspace.", + "name": "bash", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "cwd": { + "description": "Working directory for the script. Defaults to / (the workspace root)", + "type": "string" + }, + "script": { + "description": "Bash script to run", + "type": "string" + } + }, + "required": ["script"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Get deterministic weather for a city.", + "name": "lookup_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "city": { + "type": "string" + } + }, + "required": ["city"], + "type": "object" + } + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/chat/completions" + }, + "response": { + "body": { + "chunks": [ + "data: {\"id\":\"chatcmpl-E3jdys08eYN4lL67RNwOnxhC55ciz\",\"object\":\"chat.completion.chunk\",\"created\":1784559146,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"refusal\":null},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"Iuoer\"}", + "data: {\"id\":\"chatcmpl-E3jdys08eYN4lL67RNwOnxhC55ciz\",\"object\":\"chat.completion.chunk\",\"created\":1784559146,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"Vien\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"Omd\"}", + "data: {\"id\":\"chatcmpl-E3jdys08eYN4lL67RNwOnxhC55ciz\",\"object\":\"chat.completion.chunk\",\"created\":1784559146,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"na\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"Bz1Y0\"}", + "data: {\"id\":\"chatcmpl-E3jdys08eYN4lL67RNwOnxhC55ciz\",\"object\":\"chat.completion.chunk\",\"created\":1784559146,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" is\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"BWed\"}", + "data: {\"id\":\"chatcmpl-E3jdys08eYN4lL67RNwOnxhC55ciz\",\"object\":\"chat.completion.chunk\",\"created\":1784559146,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" sunny\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"D\"}", + "data: {\"id\":\"chatcmpl-E3jdys08eYN4lL67RNwOnxhC55ciz\",\"object\":\"chat.completion.chunk\",\"created\":1784559146,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" and\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"0FB\"}", + "data: {\"id\":\"chatcmpl-E3jdys08eYN4lL67RNwOnxhC55ciz\",\"object\":\"chat.completion.chunk\",\"created\":1784559146,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"D2rUzB\"}", + "data: {\"id\":\"chatcmpl-E3jdys08eYN4lL67RNwOnxhC55ciz\",\"object\":\"chat.completion.chunk\",\"created\":1784559146,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"21\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"PtMcu\"}", + "data: {\"id\":\"chatcmpl-E3jdys08eYN4lL67RNwOnxhC55ciz\",\"object\":\"chat.completion.chunk\",\"created\":1784559146,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"°C\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"KF6c5\"}", + "data: {\"id\":\"chatcmpl-E3jdys08eYN4lL67RNwOnxhC55ciz\",\"object\":\"chat.completion.chunk\",\"created\":1784559146,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\".\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"l3Afxb\"}", + "data: {\"id\":\"chatcmpl-E3jdys08eYN4lL67RNwOnxhC55ciz\",\"object\":\"chat.completion.chunk\",\"created\":1784559146,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}],\"usage\":null,\"obfuscation\":\"3\"}", + "data: {\"id\":\"chatcmpl-E3jdys08eYN4lL67RNwOnxhC55ciz\",\"object\":\"chat.completion.chunk\",\"created\":1784559146,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[],\"usage\":{\"prompt_tokens\":1087,\"completion_tokens\":210,\"total_tokens\":1297,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":192,\"audio_tokens\":0,\"accepted_prediction_tokens\":0,\"rejected_prediction_tokens\":0}},\"obfuscation\":\"B6kJ0BZeZqChWQT\"}", + "data: [DONE]" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a1e2ca25aa20c946-IAD", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 20 Jul 2026 14:52:27 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "1894", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "30000", + "x-ratelimit-limit-tokens": "180000000", + "x-ratelimit-remaining-requests": "29999", + "x-ratelimit-remaining-tokens": "179999790", + "x-ratelimit-reset-requests": "2ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_585765b7523241a38133f2b76492d7ad" + }, + "status": 200, + "statusText": "OK" + } + } + ], + "meta": { + "createdAt": "2026-07-20T14:52:28.130Z" + } +} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-latest-manual.cassette.json b/e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-latest-manual.cassette.json new file mode 100644 index 000000000..e784c5828 --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-latest-manual.cassette.json @@ -0,0 +1,651 @@ +{ + "entries": [ + { + "callIndex": 0, + "id": "02bfffc5f7e45fcc", + "matchKey": "POST api.openai.com/v1/chat/completions", + "recordedAt": "2026-07-20T14:52:10.061Z", + "request": { + "body": { + "kind": "json", + "value": { + "messages": [ + { + "content": "You are a deterministic weather-test agent. You must call lookup_weather exactly once with Vienna before answering. After the tool result, reply with exactly: \"Vienna is sunny and 21°C.\"\n\nYou are running inside a Think agent.\n\nCapabilities available in this turn:\n- You can inspect and edit the agent workspace using the available file tools.\n- Use the tools exposed in this turn when they materially improve accuracy or let you act on the user's request. Treat tool descriptions and schemas as the source of truth.\n- Some tools may call server code, browser/client code, MCP servers, extensions, or delegated agents. Use them according to their descriptions.\n- Do not claim access to capabilities that are not exposed as tools in this turn.", + "role": "developer" + }, + { + "content": "What is the weather in Vienna?", + "role": "user" + } + ], + "model": "gpt-5-nano", + "stream": true, + "stream_options": { + "include_usage": true + }, + "tool_choice": "auto", + "tools": [ + { + "function": { + "description": "Read a workspace file. Text files return line-numbered content. Images and PDFs are passed to capable models as file content. Use offset and limit for large text files. Returns null if the file does not exist.", + "name": "read", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Number of lines to read", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "1-indexed line number to start reading from", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Write content to a file. Creates the file if it does not exist, overwrites if it does. Parent directories are created automatically.", + "name": "write", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Make a targeted edit to a file by replacing an exact string match. Provide the old_string to find and new_string to replace it with. The old_string must match exactly (including whitespace and indentation). Use an empty old_string with new_string to create a new file.", + "name": "edit", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "new_string": { + "description": "Replacement text", + "type": "string" + }, + "old_string": { + "description": "Exact text to find and replace. Empty string to create a new file.", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "old_string", "new_string"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "List files and directories in a given path. Returns names, types, and sizes for each entry.", + "name": "list", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Maximum number of entries to return (default: 200)", + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "Number of entries to skip (for pagination)", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "path": { + "default": "/", + "description": "Absolute path to the directory to list", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Find files matching a glob pattern. Supports standard glob syntax: * matches any file, ** matches directories recursively, ? matches a single character. Returns matching file paths with types and sizes.", + "name": "find", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "pattern": { + "description": "Glob pattern to match (e.g. \"**/*.ts\", \"src/**/*.test.ts\", \"*.md\")", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Search file contents using a regular expression or fixed string. Returns matching lines with file paths and line numbers. Searches all files matching the include glob, or all files if not specified.", + "name": "grep", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "caseSensitive": { + "description": "If true, search is case-sensitive (default: false)", + "type": "boolean" + }, + "contextLines": { + "description": "Number of context lines around each match (default: 0)", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "fixedString": { + "description": "If true, treat query as a literal string instead of regex", + "type": "boolean" + }, + "include": { + "description": "Glob pattern to filter files (e.g. \"**/*.ts\"). Defaults to \"**/*\"", + "type": "string" + }, + "query": { + "description": "Search pattern (regex or fixed string)", + "type": "string" + } + }, + "required": ["query"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Delete a file or directory. Set recursive to true to remove non-empty directories.", + "name": "delete", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "path": { + "description": "Absolute path to the file or directory", + "type": "string" + }, + "recursive": { + "description": "If true, remove directories and their contents recursively", + "type": "boolean" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Run a Bash script against the workspace. Use for shell-style workflows that combine multiple file operations. The script runs in a sandboxed virtual filesystem with the workspace mounted at `/` (also the default working directory) — there is no `/workspace` or `/home`; use absolute paths like `/notes.txt`. Changed files are written back to the workspace.", + "name": "bash", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "cwd": { + "description": "Working directory for the script. Defaults to / (the workspace root)", + "type": "string" + }, + "script": { + "description": "Bash script to run", + "type": "string" + } + }, + "required": ["script"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Get deterministic weather for a city.", + "name": "lookup_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "city": { + "type": "string" + } + }, + "required": ["city"], + "type": "object" + } + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/chat/completions" + }, + "response": { + "body": { + "chunks": [ + "data: {\"id\":\"chatcmpl-E3jdeRufBpWdcnlvefQEVX1AaGDvd\",\"object\":\"chat.completion.chunk\",\"created\":1784559126,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"id\":\"call_Eoiiczb05o0gHVdCT1udMEQS\",\"type\":\"function\",\"function\":{\"name\":\"lookup_weather\",\"arguments\":\"\"}}],\"refusal\":null},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"x8G82KK4NhJqf\"}", + "data: {\"id\":\"chatcmpl-E3jdeRufBpWdcnlvefQEVX1AaGDvd\",\"object\":\"chat.completion.chunk\",\"created\":1784559126,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"{\\\"\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"pSTXLgOXRH\"}", + "data: {\"id\":\"chatcmpl-E3jdeRufBpWdcnlvefQEVX1AaGDvd\",\"object\":\"chat.completion.chunk\",\"created\":1784559126,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"city\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"Z0Tw1OsB1\"}", + "data: {\"id\":\"chatcmpl-E3jdeRufBpWdcnlvefQEVX1AaGDvd\",\"object\":\"chat.completion.chunk\",\"created\":1784559126,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\":\\\"\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"YlWdjNah\"}", + "data: {\"id\":\"chatcmpl-E3jdeRufBpWdcnlvefQEVX1AaGDvd\",\"object\":\"chat.completion.chunk\",\"created\":1784559126,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"Vien\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"hveMd98Be\"}", + "data: {\"id\":\"chatcmpl-E3jdeRufBpWdcnlvefQEVX1AaGDvd\",\"object\":\"chat.completion.chunk\",\"created\":1784559126,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"na\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"Q2kiGorklVn\"}", + "data: {\"id\":\"chatcmpl-E3jdeRufBpWdcnlvefQEVX1AaGDvd\",\"object\":\"chat.completion.chunk\",\"created\":1784559126,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\"}\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"TUAPImAvI5\"}", + "data: {\"id\":\"chatcmpl-E3jdeRufBpWdcnlvefQEVX1AaGDvd\",\"object\":\"chat.completion.chunk\",\"created\":1784559126,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"tool_calls\"}],\"usage\":null,\"obfuscation\":\"xDHwRJsdaf1\"}", + "data: {\"id\":\"chatcmpl-E3jdeRufBpWdcnlvefQEVX1AaGDvd\",\"object\":\"chat.completion.chunk\",\"created\":1784559126,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[],\"usage\":{\"prompt_tokens\":1042,\"completion_tokens\":472,\"total_tokens\":1514,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":448,\"audio_tokens\":0,\"accepted_prediction_tokens\":0,\"rejected_prediction_tokens\":0}},\"obfuscation\":\"hzudExOv18nATcS\"}", + "data: [DONE]" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a1e2c9a898bad6bb-IAD", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 20 Jul 2026 14:52:09 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "4024", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "30000", + "x-ratelimit-limit-tokens": "180000000", + "x-ratelimit-remaining-requests": "29999", + "x-ratelimit-remaining-tokens": "179999802", + "x-ratelimit-reset-requests": "2ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_3528a89f02aa41f08f950f46d92d2469" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 1, + "id": "a62b9ef8bb70f1d5", + "matchKey": "POST api.openai.com/v1/chat/completions", + "recordedAt": "2026-07-20T14:52:12.986Z", + "request": { + "body": { + "kind": "json", + "value": { + "messages": [ + { + "content": "You are a deterministic weather-test agent. You must call lookup_weather exactly once with Vienna before answering. After the tool result, reply with exactly: \"Vienna is sunny and 21°C.\"\n\nYou are running inside a Think agent.\n\nCapabilities available in this turn:\n- You can inspect and edit the agent workspace using the available file tools.\n- Use the tools exposed in this turn when they materially improve accuracy or let you act on the user's request. Treat tool descriptions and schemas as the source of truth.\n- Some tools may call server code, browser/client code, MCP servers, extensions, or delegated agents. Use them according to their descriptions.\n- Do not claim access to capabilities that are not exposed as tools in this turn.", + "role": "developer" + }, + { + "content": "What is the weather in Vienna?", + "role": "user" + }, + { + "content": null, + "role": "assistant", + "tool_calls": [ + { + "function": { + "arguments": "{\"city\":\"Vienna\"}", + "name": "lookup_weather" + }, + "id": "call_Eoiiczb05o0gHVdCT1udMEQS", + "type": "function" + } + ] + }, + { + "content": "{\"city\":\"Vienna\",\"condition\":\"sunny\",\"degreesC\":21}", + "role": "tool", + "tool_call_id": "call_Eoiiczb05o0gHVdCT1udMEQS" + } + ], + "model": "gpt-5-nano", + "stream": true, + "stream_options": { + "include_usage": true + }, + "tool_choice": "auto", + "tools": [ + { + "function": { + "description": "Read a workspace file. Text files return line-numbered content. Images and PDFs are passed to capable models as file content. Use offset and limit for large text files. Returns null if the file does not exist.", + "name": "read", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Number of lines to read", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "1-indexed line number to start reading from", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Write content to a file. Creates the file if it does not exist, overwrites if it does. Parent directories are created automatically.", + "name": "write", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Make a targeted edit to a file by replacing an exact string match. Provide the old_string to find and new_string to replace it with. The old_string must match exactly (including whitespace and indentation). Use an empty old_string with new_string to create a new file.", + "name": "edit", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "new_string": { + "description": "Replacement text", + "type": "string" + }, + "old_string": { + "description": "Exact text to find and replace. Empty string to create a new file.", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "old_string", "new_string"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "List files and directories in a given path. Returns names, types, and sizes for each entry.", + "name": "list", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Maximum number of entries to return (default: 200)", + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "Number of entries to skip (for pagination)", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "path": { + "default": "/", + "description": "Absolute path to the directory to list", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Find files matching a glob pattern. Supports standard glob syntax: * matches any file, ** matches directories recursively, ? matches a single character. Returns matching file paths with types and sizes.", + "name": "find", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "pattern": { + "description": "Glob pattern to match (e.g. \"**/*.ts\", \"src/**/*.test.ts\", \"*.md\")", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Search file contents using a regular expression or fixed string. Returns matching lines with file paths and line numbers. Searches all files matching the include glob, or all files if not specified.", + "name": "grep", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "caseSensitive": { + "description": "If true, search is case-sensitive (default: false)", + "type": "boolean" + }, + "contextLines": { + "description": "Number of context lines around each match (default: 0)", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "fixedString": { + "description": "If true, treat query as a literal string instead of regex", + "type": "boolean" + }, + "include": { + "description": "Glob pattern to filter files (e.g. \"**/*.ts\"). Defaults to \"**/*\"", + "type": "string" + }, + "query": { + "description": "Search pattern (regex or fixed string)", + "type": "string" + } + }, + "required": ["query"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Delete a file or directory. Set recursive to true to remove non-empty directories.", + "name": "delete", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "path": { + "description": "Absolute path to the file or directory", + "type": "string" + }, + "recursive": { + "description": "If true, remove directories and their contents recursively", + "type": "boolean" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Run a Bash script against the workspace. Use for shell-style workflows that combine multiple file operations. The script runs in a sandboxed virtual filesystem with the workspace mounted at `/` (also the default working directory) — there is no `/workspace` or `/home`; use absolute paths like `/notes.txt`. Changed files are written back to the workspace.", + "name": "bash", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "cwd": { + "description": "Working directory for the script. Defaults to / (the workspace root)", + "type": "string" + }, + "script": { + "description": "Bash script to run", + "type": "string" + } + }, + "required": ["script"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Get deterministic weather for a city.", + "name": "lookup_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "city": { + "type": "string" + } + }, + "required": ["city"], + "type": "object" + } + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/chat/completions" + }, + "response": { + "body": { + "chunks": [ + "data: {\"id\":\"chatcmpl-E3jdik7STRo6NkYMCy1Eo7QC9KmO0\",\"object\":\"chat.completion.chunk\",\"created\":1784559130,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"refusal\":null},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"VuZbb\"}", + "data: {\"id\":\"chatcmpl-E3jdik7STRo6NkYMCy1Eo7QC9KmO0\",\"object\":\"chat.completion.chunk\",\"created\":1784559130,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"Vien\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"oam\"}", + "data: {\"id\":\"chatcmpl-E3jdik7STRo6NkYMCy1Eo7QC9KmO0\",\"object\":\"chat.completion.chunk\",\"created\":1784559130,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"na\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"PUiJI\"}", + "data: {\"id\":\"chatcmpl-E3jdik7STRo6NkYMCy1Eo7QC9KmO0\",\"object\":\"chat.completion.chunk\",\"created\":1784559130,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" is\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"BeE7\"}", + "data: {\"id\":\"chatcmpl-E3jdik7STRo6NkYMCy1Eo7QC9KmO0\",\"object\":\"chat.completion.chunk\",\"created\":1784559130,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" sunny\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"V\"}", + "data: {\"id\":\"chatcmpl-E3jdik7STRo6NkYMCy1Eo7QC9KmO0\",\"object\":\"chat.completion.chunk\",\"created\":1784559130,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" and\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"nWm\"}", + "data: {\"id\":\"chatcmpl-E3jdik7STRo6NkYMCy1Eo7QC9KmO0\",\"object\":\"chat.completion.chunk\",\"created\":1784559130,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"KsqkxC\"}", + "data: {\"id\":\"chatcmpl-E3jdik7STRo6NkYMCy1Eo7QC9KmO0\",\"object\":\"chat.completion.chunk\",\"created\":1784559130,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"21\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"5IY1X\"}", + "data: {\"id\":\"chatcmpl-E3jdik7STRo6NkYMCy1Eo7QC9KmO0\",\"object\":\"chat.completion.chunk\",\"created\":1784559130,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"°C\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"MclDT\"}", + "data: {\"id\":\"chatcmpl-E3jdik7STRo6NkYMCy1Eo7QC9KmO0\",\"object\":\"chat.completion.chunk\",\"created\":1784559130,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\".\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"lcmbyj\"}", + "data: {\"id\":\"chatcmpl-E3jdik7STRo6NkYMCy1Eo7QC9KmO0\",\"object\":\"chat.completion.chunk\",\"created\":1784559130,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}],\"usage\":null,\"obfuscation\":\"V\"}", + "data: {\"id\":\"chatcmpl-E3jdik7STRo6NkYMCy1Eo7QC9KmO0\",\"object\":\"chat.completion.chunk\",\"created\":1784559130,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[],\"usage\":{\"prompt_tokens\":1087,\"completion_tokens\":338,\"total_tokens\":1425,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":320,\"audio_tokens\":0,\"accepted_prediction_tokens\":0,\"rejected_prediction_tokens\":0}},\"obfuscation\":\"H2zk3oOvqddJbZo\"}", + "data: [DONE]" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a1e2c9c33cc4d6bb-IAD", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 20 Jul 2026 14:52:12 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "2412", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "30000", + "x-ratelimit-limit-tokens": "180000000", + "x-ratelimit-remaining-requests": "29999", + "x-ratelimit-remaining-tokens": "179999790", + "x-ratelimit-reset-requests": "2ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_5a41953636984f51aea4495cd220e137" + }, + "status": 200, + "statusText": "OK" + } + } + ], + "meta": { + "createdAt": "2026-07-20T14:52:13.192Z" + } +} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-manual.cassette.json b/e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-manual.cassette.json new file mode 100644 index 000000000..b6e03711f --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/__cassettes__/cloudflare-think-v0-manual.cassette.json @@ -0,0 +1,651 @@ +{ + "entries": [ + { + "callIndex": 0, + "id": "02bfffc5f7e45fcc", + "matchKey": "POST api.openai.com/v1/chat/completions", + "recordedAt": "2026-07-20T14:51:40.635Z", + "request": { + "body": { + "kind": "json", + "value": { + "messages": [ + { + "content": "You are a deterministic weather-test agent. You must call lookup_weather exactly once with Vienna before answering. After the tool result, reply with exactly: \"Vienna is sunny and 21°C.\"\n\nYou are running inside a Think agent.\n\nCapabilities available in this turn:\n- You can inspect and edit the agent workspace using the available file tools.\n- Use the tools exposed in this turn when they materially improve accuracy or let you act on the user's request. Treat tool descriptions and schemas as the source of truth.\n- Some tools may call server code, browser/client code, MCP servers, extensions, or delegated agents. Use them according to their descriptions.\n- Do not claim access to capabilities that are not exposed as tools in this turn.", + "role": "developer" + }, + { + "content": "What is the weather in Vienna?", + "role": "user" + } + ], + "model": "gpt-5-nano", + "stream": true, + "stream_options": { + "include_usage": true + }, + "tool_choice": "auto", + "tools": [ + { + "function": { + "description": "Read a workspace file. Text files return line-numbered content. Images and PDFs are passed to capable models as file content. Use offset and limit for large text files. Returns null if the file does not exist.", + "name": "read", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Number of lines to read", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "1-indexed line number to start reading from", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Write content to a file. Creates the file if it does not exist, overwrites if it does. Parent directories are created automatically.", + "name": "write", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Make a targeted edit to a file by replacing an exact string match. Provide the old_string to find and new_string to replace it with. The old_string must match exactly (including whitespace and indentation). Use an empty old_string with new_string to create a new file.", + "name": "edit", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "new_string": { + "description": "Replacement text", + "type": "string" + }, + "old_string": { + "description": "Exact text to find and replace. Empty string to create a new file.", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "old_string", "new_string"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "List files and directories in a given path. Returns names, types, and sizes for each entry.", + "name": "list", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Maximum number of entries to return (default: 200)", + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "Number of entries to skip (for pagination)", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "path": { + "default": "/", + "description": "Absolute path to the directory to list", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Find files matching a glob pattern. Supports standard glob syntax: * matches any file, ** matches directories recursively, ? matches a single character. Returns matching file paths with types and sizes.", + "name": "find", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "pattern": { + "description": "Glob pattern to match (e.g. \"**/*.ts\", \"src/**/*.test.ts\", \"*.md\")", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Search file contents using a regular expression or fixed string. Returns matching lines with file paths and line numbers. Searches all files matching the include glob, or all files if not specified.", + "name": "grep", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "caseSensitive": { + "description": "If true, search is case-sensitive (default: false)", + "type": "boolean" + }, + "contextLines": { + "description": "Number of context lines around each match (default: 0)", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "fixedString": { + "description": "If true, treat query as a literal string instead of regex", + "type": "boolean" + }, + "include": { + "description": "Glob pattern to filter files (e.g. \"**/*.ts\"). Defaults to \"**/*\"", + "type": "string" + }, + "query": { + "description": "Search pattern (regex or fixed string)", + "type": "string" + } + }, + "required": ["query"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Delete a file or directory. Set recursive to true to remove non-empty directories.", + "name": "delete", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "path": { + "description": "Absolute path to the file or directory", + "type": "string" + }, + "recursive": { + "description": "If true, remove directories and their contents recursively", + "type": "boolean" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Run a Bash script against the workspace. Use for shell-style workflows that combine multiple file operations. The script runs in a sandboxed virtual filesystem with the workspace mounted at `/` (also the default working directory) — there is no `/workspace` or `/home`; use absolute paths like `/notes.txt`. Changed files are written back to the workspace.", + "name": "bash", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "cwd": { + "description": "Working directory for the script. Defaults to / (the workspace root)", + "type": "string" + }, + "script": { + "description": "Bash script to run", + "type": "string" + } + }, + "required": ["script"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Get deterministic weather for a city.", + "name": "lookup_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "city": { + "type": "string" + } + }, + "required": ["city"], + "type": "object" + } + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/chat/completions" + }, + "response": { + "body": { + "chunks": [ + "data: {\"id\":\"chatcmpl-E3jdCRD2ZdXjpM0joLJxiTap2PYTn\",\"object\":\"chat.completion.chunk\",\"created\":1784559098,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"id\":\"call_B5b5ExUj3UtB8q7ozaR2RcFh\",\"type\":\"function\",\"function\":{\"name\":\"lookup_weather\",\"arguments\":\"\"}}],\"refusal\":null},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"XEIiGtn1InYQM\"}", + "data: {\"id\":\"chatcmpl-E3jdCRD2ZdXjpM0joLJxiTap2PYTn\",\"object\":\"chat.completion.chunk\",\"created\":1784559098,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"{\\\"\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"FknhY5rnVu\"}", + "data: {\"id\":\"chatcmpl-E3jdCRD2ZdXjpM0joLJxiTap2PYTn\",\"object\":\"chat.completion.chunk\",\"created\":1784559098,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"city\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"vtkhNcZlp\"}", + "data: {\"id\":\"chatcmpl-E3jdCRD2ZdXjpM0joLJxiTap2PYTn\",\"object\":\"chat.completion.chunk\",\"created\":1784559098,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\":\\\"\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"vMt5jEko\"}", + "data: {\"id\":\"chatcmpl-E3jdCRD2ZdXjpM0joLJxiTap2PYTn\",\"object\":\"chat.completion.chunk\",\"created\":1784559098,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"Vien\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"FFP6W0KNT\"}", + "data: {\"id\":\"chatcmpl-E3jdCRD2ZdXjpM0joLJxiTap2PYTn\",\"object\":\"chat.completion.chunk\",\"created\":1784559098,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"na\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"7oWJEwQWZVS\"}", + "data: {\"id\":\"chatcmpl-E3jdCRD2ZdXjpM0joLJxiTap2PYTn\",\"object\":\"chat.completion.chunk\",\"created\":1784559098,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\"}\"}}]},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"KW01qh0PNy\"}", + "data: {\"id\":\"chatcmpl-E3jdCRD2ZdXjpM0joLJxiTap2PYTn\",\"object\":\"chat.completion.chunk\",\"created\":1784559098,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"tool_calls\"}],\"usage\":null,\"obfuscation\":\"12KTjMtL8HI\"}", + "data: {\"id\":\"chatcmpl-E3jdCRD2ZdXjpM0joLJxiTap2PYTn\",\"object\":\"chat.completion.chunk\",\"created\":1784559098,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[],\"usage\":{\"prompt_tokens\":1042,\"completion_tokens\":408,\"total_tokens\":1450,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":384,\"audio_tokens\":0,\"accepted_prediction_tokens\":0,\"rejected_prediction_tokens\":0}},\"obfuscation\":\"B8HBw8SlSXErNSJ\"}", + "data: [DONE]" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a1e2c8f8bf98d860-IAD", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 20 Jul 2026 14:51:40 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "2698", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "30000", + "x-ratelimit-limit-tokens": "180000000", + "x-ratelimit-remaining-requests": "29999", + "x-ratelimit-remaining-tokens": "179999802", + "x-ratelimit-reset-requests": "2ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_d111d16fb6e647a190d222ba7215b58e" + }, + "status": 200, + "statusText": "OK" + } + }, + { + "callIndex": 1, + "id": "888ecd04b50ae481", + "matchKey": "POST api.openai.com/v1/chat/completions", + "recordedAt": "2026-07-20T14:51:42.667Z", + "request": { + "body": { + "kind": "json", + "value": { + "messages": [ + { + "content": "You are a deterministic weather-test agent. You must call lookup_weather exactly once with Vienna before answering. After the tool result, reply with exactly: \"Vienna is sunny and 21°C.\"\n\nYou are running inside a Think agent.\n\nCapabilities available in this turn:\n- You can inspect and edit the agent workspace using the available file tools.\n- Use the tools exposed in this turn when they materially improve accuracy or let you act on the user's request. Treat tool descriptions and schemas as the source of truth.\n- Some tools may call server code, browser/client code, MCP servers, extensions, or delegated agents. Use them according to their descriptions.\n- Do not claim access to capabilities that are not exposed as tools in this turn.", + "role": "developer" + }, + { + "content": "What is the weather in Vienna?", + "role": "user" + }, + { + "content": null, + "role": "assistant", + "tool_calls": [ + { + "function": { + "arguments": "{\"city\":\"Vienna\"}", + "name": "lookup_weather" + }, + "id": "call_B5b5ExUj3UtB8q7ozaR2RcFh", + "type": "function" + } + ] + }, + { + "content": "{\"city\":\"Vienna\",\"condition\":\"sunny\",\"degreesC\":21}", + "role": "tool", + "tool_call_id": "call_B5b5ExUj3UtB8q7ozaR2RcFh" + } + ], + "model": "gpt-5-nano", + "stream": true, + "stream_options": { + "include_usage": true + }, + "tool_choice": "auto", + "tools": [ + { + "function": { + "description": "Read a workspace file. Text files return line-numbered content. Images and PDFs are passed to capable models as file content. Use offset and limit for large text files. Returns null if the file does not exist.", + "name": "read", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Number of lines to read", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "1-indexed line number to start reading from", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Write content to a file. Creates the file if it does not exist, overwrites if it does. Parent directories are created automatically.", + "name": "write", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "content": { + "description": "Content to write to the file", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "content"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Make a targeted edit to a file by replacing an exact string match. Provide the old_string to find and new_string to replace it with. The old_string must match exactly (including whitespace and indentation). Use an empty old_string with new_string to create a new file.", + "name": "edit", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "new_string": { + "description": "Replacement text", + "type": "string" + }, + "old_string": { + "description": "Exact text to find and replace. Empty string to create a new file.", + "type": "string" + }, + "path": { + "description": "Absolute path to the file", + "type": "string" + } + }, + "required": ["path", "old_string", "new_string"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "List files and directories in a given path. Returns names, types, and sizes for each entry.", + "name": "list", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "limit": { + "description": "Maximum number of entries to return (default: 200)", + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + "offset": { + "description": "Number of entries to skip (for pagination)", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "path": { + "default": "/", + "description": "Absolute path to the directory to list", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Find files matching a glob pattern. Supports standard glob syntax: * matches any file, ** matches directories recursively, ? matches a single character. Returns matching file paths with types and sizes.", + "name": "find", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "pattern": { + "description": "Glob pattern to match (e.g. \"**/*.ts\", \"src/**/*.test.ts\", \"*.md\")", + "type": "string" + } + }, + "required": ["pattern"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Search file contents using a regular expression or fixed string. Returns matching lines with file paths and line numbers. Searches all files matching the include glob, or all files if not specified.", + "name": "grep", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "caseSensitive": { + "description": "If true, search is case-sensitive (default: false)", + "type": "boolean" + }, + "contextLines": { + "description": "Number of context lines around each match (default: 0)", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "fixedString": { + "description": "If true, treat query as a literal string instead of regex", + "type": "boolean" + }, + "include": { + "description": "Glob pattern to filter files (e.g. \"**/*.ts\"). Defaults to \"**/*\"", + "type": "string" + }, + "query": { + "description": "Search pattern (regex or fixed string)", + "type": "string" + } + }, + "required": ["query"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Delete a file or directory. Set recursive to true to remove non-empty directories.", + "name": "delete", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "path": { + "description": "Absolute path to the file or directory", + "type": "string" + }, + "recursive": { + "description": "If true, remove directories and their contents recursively", + "type": "boolean" + } + }, + "required": ["path"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Run a Bash script against the workspace. Use for shell-style workflows that combine multiple file operations. The script runs in a sandboxed virtual filesystem with the workspace mounted at `/` (also the default working directory) — there is no `/workspace` or `/home`; use absolute paths like `/notes.txt`. Changed files are written back to the workspace.", + "name": "bash", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "cwd": { + "description": "Working directory for the script. Defaults to / (the workspace root)", + "type": "string" + }, + "script": { + "description": "Bash script to run", + "type": "string" + } + }, + "required": ["script"], + "type": "object" + } + }, + "type": "function" + }, + { + "function": { + "description": "Get deterministic weather for a city.", + "name": "lookup_weather", + "parameters": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "city": { + "type": "string" + } + }, + "required": ["city"], + "type": "object" + } + }, + "type": "function" + } + ] + } + }, + "headers": {}, + "method": "POST", + "url": "https://api.openai.com/v1/chat/completions" + }, + "response": { + "body": { + "chunks": [ + "data: {\"id\":\"chatcmpl-E3jdFRXsUNgVqL3xX7fwggT9H1eHI\",\"object\":\"chat.completion.chunk\",\"created\":1784559101,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"refusal\":null},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"c6Ldt\"}", + "data: {\"id\":\"chatcmpl-E3jdFRXsUNgVqL3xX7fwggT9H1eHI\",\"object\":\"chat.completion.chunk\",\"created\":1784559101,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"Vien\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"M8y\"}", + "data: {\"id\":\"chatcmpl-E3jdFRXsUNgVqL3xX7fwggT9H1eHI\",\"object\":\"chat.completion.chunk\",\"created\":1784559101,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"na\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"nrAXw\"}", + "data: {\"id\":\"chatcmpl-E3jdFRXsUNgVqL3xX7fwggT9H1eHI\",\"object\":\"chat.completion.chunk\",\"created\":1784559101,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" is\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"k8TL\"}", + "data: {\"id\":\"chatcmpl-E3jdFRXsUNgVqL3xX7fwggT9H1eHI\",\"object\":\"chat.completion.chunk\",\"created\":1784559101,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" sunny\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"O\"}", + "data: {\"id\":\"chatcmpl-E3jdFRXsUNgVqL3xX7fwggT9H1eHI\",\"object\":\"chat.completion.chunk\",\"created\":1784559101,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" and\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"7Ch\"}", + "data: {\"id\":\"chatcmpl-E3jdFRXsUNgVqL3xX7fwggT9H1eHI\",\"object\":\"chat.completion.chunk\",\"created\":1784559101,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"B6awI3\"}", + "data: {\"id\":\"chatcmpl-E3jdFRXsUNgVqL3xX7fwggT9H1eHI\",\"object\":\"chat.completion.chunk\",\"created\":1784559101,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"21\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"Vzybo\"}", + "data: {\"id\":\"chatcmpl-E3jdFRXsUNgVqL3xX7fwggT9H1eHI\",\"object\":\"chat.completion.chunk\",\"created\":1784559101,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\"°C\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"pLg3X\"}", + "data: {\"id\":\"chatcmpl-E3jdFRXsUNgVqL3xX7fwggT9H1eHI\",\"object\":\"chat.completion.chunk\",\"created\":1784559101,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{\"content\":\".\"},\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"uSFWLq\"}", + "data: {\"id\":\"chatcmpl-E3jdFRXsUNgVqL3xX7fwggT9H1eHI\",\"object\":\"chat.completion.chunk\",\"created\":1784559101,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}],\"usage\":null,\"obfuscation\":\"k\"}", + "data: {\"id\":\"chatcmpl-E3jdFRXsUNgVqL3xX7fwggT9H1eHI\",\"object\":\"chat.completion.chunk\",\"created\":1784559101,\"model\":\"gpt-5-nano-2025-08-07\",\"service_tier\":\"default\",\"system_fingerprint\":null,\"choices\":[],\"usage\":{\"prompt_tokens\":1087,\"completion_tokens\":210,\"total_tokens\":1297,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":192,\"audio_tokens\":0,\"accepted_prediction_tokens\":0,\"rejected_prediction_tokens\":0}},\"obfuscation\":\"Kb0608Kpte5vdnr\"}", + "data: [DONE]" + ], + "kind": "sse" + }, + "headers": { + "access-control-expose-headers": "X-Request-ID, CF-Ray, CF-Ray", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "a1e2c90b595ed860-IAD", + "connection": "keep-alive", + "content-type": "text/event-stream; charset=utf-8", + "date": "Mon, 20 Jul 2026 14:51:42 GMT", + "openai-organization": "braintrust-data", + "openai-processing-ms": "1803", + "openai-project": "proj_vsCSXafhhByzWOThMrJcZiw9", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "[REDACTED]", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "30000", + "x-ratelimit-limit-tokens": "180000000", + "x-ratelimit-remaining-requests": "29999", + "x-ratelimit-remaining-tokens": "179999787", + "x-ratelimit-reset-requests": "2ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_86fd123f746047a3be732d88d5d2adbc" + }, + "status": 200, + "statusText": "OK" + } + } + ], + "meta": { + "createdAt": "2026-07-20T14:51:42.895Z" + } +} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-auto.span-tree.json b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-auto.span-tree.json new file mode 100644 index 000000000..7fff031e8 --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-auto.span-tree.json @@ -0,0 +1,79 @@ +{ + "span_tree": [ + { + "name": "Think.runTurn", + "type": "task", + "children": [ + { + "name": "doStream", + "type": "llm", + "children": [], + "metadata": { + "model": "gpt-5-nano", + "provider": "openai.chat" + }, + "metrics": { + "completion_tokens": 152, + "prompt_tokens": 1042, + "tokens": 1194 + } + }, + { + "name": "lookup_weather", + "type": "tool", + "children": [], + "input": { + "city": "Vienna" + }, + "output": { + "city": "Vienna", + "condition": "sunny", + "degreesC": 21 + } + }, + { + "name": "doStream", + "type": "llm", + "children": [], + "metadata": { + "model": "gpt-5-nano", + "provider": "openai.chat" + }, + "metrics": { + "completion_tokens": 147, + "prompt_tokens": 1087, + "tokens": 1234 + } + } + ], + "input": [ + { + "content": [ + { + "text": "What is the weather in Vienna?", + "type": "text" + } + ], + "role": "user" + } + ], + "output": { + "content": "Vienna is sunny and 21°C.", + "role": "assistant" + }, + "metadata": { + "braintrust": { + "integration_name": "cloudflare-think", + "sdk_language": "typescript" + }, + "model": "gpt-5-nano", + "provider": "openai.chat" + }, + "metrics": { + "completion_tokens": 299, + "prompt_tokens": 2129, + "tokens": 2428 + } + } + ] +} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-auto.span-tree.txt b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-auto.span-tree.txt new file mode 100644 index 000000000..d1c7fa0ef --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-auto.span-tree.txt @@ -0,0 +1,59 @@ +span_tree: +└── Think.runTurn [task] + input: [ + { + "content": [ + { + "text": "What is the weather in Vienna?", + "type": "text" + } + ], + "role": "user" + } + ] + output: { + "content": "Vienna is sunny and 21°C.", + "role": "assistant" + } + metadata: { + "braintrust": { + "integration_name": "cloudflare-think", + "sdk_language": "typescript" + }, + "model": "gpt-5-nano", + "provider": "openai.chat" + } + metrics: { + "completion_tokens": 299, + "prompt_tokens": 2129, + "tokens": 2428 + } + ├── doStream [llm] + │ metadata: { + │ "model": "gpt-5-nano", + │ "provider": "openai.chat" + │ } + │ metrics: { + │ "completion_tokens": 152, + │ "prompt_tokens": 1042, + │ "tokens": 1194 + │ } + ├── lookup_weather [tool] + │ input: { + │ "city": "Vienna" + │ } + │ output: { + │ "city": "Vienna", + │ "condition": "sunny", + │ "degreesC": 21 + │ } + └── doStream [llm] + metadata: { + "model": "gpt-5-nano", + "provider": "openai.chat" + } + metrics: { + "completion_tokens": 147, + "prompt_tokens": 1087, + "tokens": 1234 + } diff --git a/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-auto.span-tree.json b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-auto.span-tree.json new file mode 100644 index 000000000..ae570646f --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-auto.span-tree.json @@ -0,0 +1,79 @@ +{ + "span_tree": [ + { + "name": "Think.runTurn", + "type": "task", + "children": [ + { + "name": "doStream", + "type": "llm", + "children": [], + "metadata": { + "model": "gpt-5-nano", + "provider": "openai.chat" + }, + "metrics": { + "completion_tokens": 344, + "prompt_tokens": 1042, + "tokens": 1386 + } + }, + { + "name": "lookup_weather", + "type": "tool", + "children": [], + "input": { + "city": "Vienna" + }, + "output": { + "city": "Vienna", + "condition": "sunny", + "degreesC": 21 + } + }, + { + "name": "doStream", + "type": "llm", + "children": [], + "metadata": { + "model": "gpt-5-nano", + "provider": "openai.chat" + }, + "metrics": { + "completion_tokens": 210, + "prompt_tokens": 1087, + "tokens": 1297 + } + } + ], + "input": [ + { + "content": [ + { + "text": "What is the weather in Vienna?", + "type": "text" + } + ], + "role": "user" + } + ], + "output": { + "content": "Vienna is sunny and 21°C.", + "role": "assistant" + }, + "metadata": { + "braintrust": { + "integration_name": "cloudflare-think", + "sdk_language": "typescript" + }, + "model": "gpt-5-nano", + "provider": "openai.chat" + }, + "metrics": { + "completion_tokens": 554, + "prompt_tokens": 2129, + "tokens": 2683 + } + } + ] +} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-auto.span-tree.txt b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-auto.span-tree.txt new file mode 100644 index 000000000..09f1e703c --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-auto.span-tree.txt @@ -0,0 +1,59 @@ +span_tree: +└── Think.runTurn [task] + input: [ + { + "content": [ + { + "text": "What is the weather in Vienna?", + "type": "text" + } + ], + "role": "user" + } + ] + output: { + "content": "Vienna is sunny and 21°C.", + "role": "assistant" + } + metadata: { + "braintrust": { + "integration_name": "cloudflare-think", + "sdk_language": "typescript" + }, + "model": "gpt-5-nano", + "provider": "openai.chat" + } + metrics: { + "completion_tokens": 554, + "prompt_tokens": 2129, + "tokens": 2683 + } + ├── doStream [llm] + │ metadata: { + │ "model": "gpt-5-nano", + │ "provider": "openai.chat" + │ } + │ metrics: { + │ "completion_tokens": 344, + │ "prompt_tokens": 1042, + │ "tokens": 1386 + │ } + ├── lookup_weather [tool] + │ input: { + │ "city": "Vienna" + │ } + │ output: { + │ "city": "Vienna", + │ "condition": "sunny", + │ "degreesC": 21 + │ } + └── doStream [llm] + metadata: { + "model": "gpt-5-nano", + "provider": "openai.chat" + } + metrics: { + "completion_tokens": 210, + "prompt_tokens": 1087, + "tokens": 1297 + } diff --git a/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-manual.span-tree.json b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-manual.span-tree.json new file mode 100644 index 000000000..9cc2cb9ca --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-manual.span-tree.json @@ -0,0 +1,79 @@ +{ + "span_tree": [ + { + "name": "Think.runTurn", + "type": "task", + "children": [ + { + "name": "doStream", + "type": "llm", + "children": [], + "metadata": { + "model": "gpt-5-nano", + "provider": "openai.chat" + }, + "metrics": { + "completion_tokens": 472, + "prompt_tokens": 1042, + "tokens": 1514 + } + }, + { + "name": "lookup_weather", + "type": "tool", + "children": [], + "input": { + "city": "Vienna" + }, + "output": { + "city": "Vienna", + "condition": "sunny", + "degreesC": 21 + } + }, + { + "name": "doStream", + "type": "llm", + "children": [], + "metadata": { + "model": "gpt-5-nano", + "provider": "openai.chat" + }, + "metrics": { + "completion_tokens": 338, + "prompt_tokens": 1087, + "tokens": 1425 + } + } + ], + "input": [ + { + "content": [ + { + "text": "What is the weather in Vienna?", + "type": "text" + } + ], + "role": "user" + } + ], + "output": { + "content": "Vienna is sunny and 21°C.", + "role": "assistant" + }, + "metadata": { + "braintrust": { + "integration_name": "cloudflare-think", + "sdk_language": "typescript" + }, + "model": "gpt-5-nano", + "provider": "openai.chat" + }, + "metrics": { + "completion_tokens": 810, + "prompt_tokens": 2129, + "tokens": 2939 + } + } + ] +} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-manual.span-tree.txt b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-manual.span-tree.txt new file mode 100644 index 000000000..886bf6f40 --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-latest-manual.span-tree.txt @@ -0,0 +1,59 @@ +span_tree: +└── Think.runTurn [task] + input: [ + { + "content": [ + { + "text": "What is the weather in Vienna?", + "type": "text" + } + ], + "role": "user" + } + ] + output: { + "content": "Vienna is sunny and 21°C.", + "role": "assistant" + } + metadata: { + "braintrust": { + "integration_name": "cloudflare-think", + "sdk_language": "typescript" + }, + "model": "gpt-5-nano", + "provider": "openai.chat" + } + metrics: { + "completion_tokens": 810, + "prompt_tokens": 2129, + "tokens": 2939 + } + ├── doStream [llm] + │ metadata: { + │ "model": "gpt-5-nano", + │ "provider": "openai.chat" + │ } + │ metrics: { + │ "completion_tokens": 472, + │ "prompt_tokens": 1042, + │ "tokens": 1514 + │ } + ├── lookup_weather [tool] + │ input: { + │ "city": "Vienna" + │ } + │ output: { + │ "city": "Vienna", + │ "condition": "sunny", + │ "degreesC": 21 + │ } + └── doStream [llm] + metadata: { + "model": "gpt-5-nano", + "provider": "openai.chat" + } + metrics: { + "completion_tokens": 338, + "prompt_tokens": 1087, + "tokens": 1425 + } diff --git a/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-manual.span-tree.json b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-manual.span-tree.json new file mode 100644 index 000000000..3decdffa8 --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-manual.span-tree.json @@ -0,0 +1,79 @@ +{ + "span_tree": [ + { + "name": "Think.runTurn", + "type": "task", + "children": [ + { + "name": "doStream", + "type": "llm", + "children": [], + "metadata": { + "model": "gpt-5-nano", + "provider": "openai.chat" + }, + "metrics": { + "completion_tokens": 408, + "prompt_tokens": 1042, + "tokens": 1450 + } + }, + { + "name": "lookup_weather", + "type": "tool", + "children": [], + "input": { + "city": "Vienna" + }, + "output": { + "city": "Vienna", + "condition": "sunny", + "degreesC": 21 + } + }, + { + "name": "doStream", + "type": "llm", + "children": [], + "metadata": { + "model": "gpt-5-nano", + "provider": "openai.chat" + }, + "metrics": { + "completion_tokens": 210, + "prompt_tokens": 1087, + "tokens": 1297 + } + } + ], + "input": [ + { + "content": [ + { + "text": "What is the weather in Vienna?", + "type": "text" + } + ], + "role": "user" + } + ], + "output": { + "content": "Vienna is sunny and 21°C.", + "role": "assistant" + }, + "metadata": { + "braintrust": { + "integration_name": "cloudflare-think", + "sdk_language": "typescript" + }, + "model": "gpt-5-nano", + "provider": "openai.chat" + }, + "metrics": { + "completion_tokens": 618, + "prompt_tokens": 2129, + "tokens": 2747 + } + } + ] +} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-manual.span-tree.txt b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-manual.span-tree.txt new file mode 100644 index 000000000..e35d19a86 --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/__snapshots__/cloudflare-think-v0-manual.span-tree.txt @@ -0,0 +1,59 @@ +span_tree: +└── Think.runTurn [task] + input: [ + { + "content": [ + { + "text": "What is the weather in Vienna?", + "type": "text" + } + ], + "role": "user" + } + ] + output: { + "content": "Vienna is sunny and 21°C.", + "role": "assistant" + } + metadata: { + "braintrust": { + "integration_name": "cloudflare-think", + "sdk_language": "typescript" + }, + "model": "gpt-5-nano", + "provider": "openai.chat" + } + metrics: { + "completion_tokens": 618, + "prompt_tokens": 2129, + "tokens": 2747 + } + ├── doStream [llm] + │ metadata: { + │ "model": "gpt-5-nano", + │ "provider": "openai.chat" + │ } + │ metrics: { + │ "completion_tokens": 408, + │ "prompt_tokens": 1042, + │ "tokens": 1450 + │ } + ├── lookup_weather [tool] + │ input: { + │ "city": "Vienna" + │ } + │ output: { + │ "city": "Vienna", + │ "condition": "sunny", + │ "degreesC": 21 + │ } + └── doStream [llm] + metadata: { + "model": "gpt-5-nano", + "provider": "openai.chat" + } + metrics: { + "completion_tokens": 210, + "prompt_tokens": 1087, + "tokens": 1297 + } diff --git a/e2e/scenarios/cloudflare-think-instrumentation/assertions.ts b/e2e/scenarios/cloudflare-think-instrumentation/assertions.ts new file mode 100644 index 000000000..7b7d6b716 --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/assertions.ts @@ -0,0 +1,187 @@ +import { beforeAll, describe, expect, test } from "vitest"; +import type { CapturedLogEvent } from "../../helpers/mock-braintrust-server"; +import { resolveFileSnapshotPath } from "../../helpers/file-snapshot"; +import { + effectiveScenarioTimeoutMs, + withScenarioHarness, + type ScenarioRunContext, +} from "../../helpers/scenario-harness"; +import { + matchSpanTreeSnapshot, + type SpanTreeFields, +} from "../../helpers/span-tree"; +import { findChildSpans, findLatestSpan } from "../../helpers/trace-selectors"; + +type ScenarioRunner = (harness: { + runScenarioDir: (options: { + entry?: string; + env?: Record; + runContext?: ScenarioRunContext; + scenarioDir: string; + timeoutMs: number; + }) => Promise; +}) => Promise; + +export function defineCloudflareThinkAssertions(options: { + name: string; + runScenario: ScenarioRunner; + snapshotName: string; + testFileUrl: string; + timeoutMs: number; +}): void { + const timeoutMs = effectiveScenarioTimeoutMs(options.timeoutMs); + const snapshotPath = resolveFileSnapshotPath( + options.testFileUrl, + `${options.snapshotName}.span-tree.json`, + ); + + describe(options.name, () => { + let events: CapturedLogEvent[] = []; + let setupError: string | undefined; + + beforeAll(async () => { + try { + await withScenarioHarness(async (harness) => { + await options.runScenario(harness); + events = harness.events(); + }); + } catch (error) { + setupError = error instanceof Error ? error.message : String(error); + } + }, timeoutMs); + + test( + "captures the spec-compliant Think agent tree", + { timeout: timeoutMs }, + () => { + expect(setupError).toBeUndefined(); + const task = findLatestSpan(events, "Think.runTurn"); + const modelSpans = findChildSpans(events, "doStream", task?.span.id); + const toolSpans = findChildSpans( + events, + "lookup_weather", + task?.span.id, + ); + + expect(task?.span.type).toBe("task"); + expect(task?.input).toEqual( + expect.arrayContaining([expect.objectContaining({ role: "user" })]), + ); + expect(JSON.stringify(task?.output)).toContain( + "Vienna is sunny and 21°C.", + ); + expect(task?.row.metadata).toMatchObject({ + braintrust: { + integration_name: "cloudflare-think", + sdk_language: "typescript", + }, + model: "gpt-5-nano", + provider: "openai.chat", + }); + expectPositiveTokenMetrics(task?.metrics); + + expect(modelSpans).toHaveLength(2); + for (const span of modelSpans) { + expect(span.span.type).toBe("llm"); + expect(span.span.parentIds).toEqual([task?.span.id]); + expect(span.row.metadata).toMatchObject({ + model: "gpt-5-nano", + provider: "openai.chat", + }); + expectPositiveTokenMetrics(span.metrics); + } + expect(task?.metrics?.prompt_tokens).toBe( + modelSpans.reduce( + (total, span) => total + (span.metrics?.prompt_tokens ?? 0), + 0, + ), + ); + expect(task?.metrics?.completion_tokens).toBe( + modelSpans.reduce( + (total, span) => total + (span.metrics?.completion_tokens ?? 0), + 0, + ), + ); + expect(toolSpans).toHaveLength(1); + expect(toolSpans[0]?.span.type).toBe("tool"); + expect(toolSpans[0]?.input).toEqual({ city: "Vienna" }); + expect(toolSpans[0]?.output).toEqual({ + city: "Vienna", + condition: "sunny", + degreesC: 21, + }); + expect(toolSpans[0]?.span.parentIds).toEqual([task?.span.id]); + expect(findLatestSpan(events, "streamText")).toBeUndefined(); + }, + ); + + test("matches the span tree snapshot", { timeout: timeoutMs }, async () => { + expect(setupError).toBeUndefined(); + const names = new Set(["Think.runTurn", "doStream", "lookup_weather"]); + const latestBySpanId = new Map(); + for (const event of events) { + if (event.span.id && event.span.name && names.has(event.span.name)) { + latestBySpanId.set(event.span.id, event); + } + } + await matchSpanTreeSnapshot( + [...latestBySpanId.values()].map((event) => ({ + event, + fields: stableThinkSpanFields(event), + })), + snapshotPath, + ); + }); + }); +} + +function expectPositiveTokenMetrics( + metrics: CapturedLogEvent["metrics"] | undefined, +): void { + expect(metrics?.prompt_tokens).toBeGreaterThan(0); + expect(metrics?.completion_tokens).toBeGreaterThan(0); + expect(metrics?.tokens).toBe( + (metrics?.prompt_tokens ?? 0) + (metrics?.completion_tokens ?? 0), + ); +} + +function stableThinkSpanFields(event: CapturedLogEvent): SpanTreeFields { + const metadata = event.metadata; + const metrics = event.metrics; + const isTask = event.span.name === "Think.runTurn"; + + return { + input: isTask + ? taskUserInput(event.input) + : event.span.type === "tool" + ? event.input + : undefined, + output: isTask || event.span.type === "tool" ? event.output : undefined, + metadata: metadata + ? { + braintrust: isTask ? metadata.braintrust : undefined, + model: metadata.model, + provider: metadata.provider, + } + : undefined, + metrics: metrics + ? { + completion_tokens: metrics.completion_tokens, + prompt_tokens: metrics.prompt_tokens, + tokens: metrics.tokens, + } + : undefined, + }; +} + +function taskUserInput(input: unknown): unknown { + return Array.isArray(input) + ? input.filter( + (message) => + typeof message === "object" && + message !== null && + "role" in message && + message.role === "user", + ) + : input; +} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/cassette-filter.mjs b/e2e/scenarios/cloudflare-think-instrumentation/cassette-filter.mjs new file mode 100644 index 000000000..5a5c39216 --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/cassette-filter.mjs @@ -0,0 +1,13 @@ +// @ts-check +/** @type {import("@braintrust/seinfeld").FilterSpec} */ +export const filter = [ + "default", + { + ignoreBodyFields: [ + "experimental_generateMessageId", + "messageId", + "messages.*.id", + "messages.*.experimental_messageId", + ], + }, +]; diff --git a/e2e/scenarios/cloudflare-think-instrumentation/package.json b/e2e/scenarios/cloudflare-think-instrumentation/package.json new file mode 100644 index 000000000..f4c11929a --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/package.json @@ -0,0 +1,28 @@ +{ + "name": "@braintrust/e2e-cloudflare-think-instrumentation", + "private": true, + "type": "module", + "braintrustScenario": { + "bump": { + "dependencies": { + "cloudflare-think-v0-latest": { + "package": "@cloudflare/think", + "range": ">=0.13.0 <0.14.0" + } + } + } + }, + "dependencies": { + "@ai-sdk/openai": "3.0.80", + "@cloudflare/vite-plugin": "1.45.1", + "agents": "0.17.4", + "ai": "6.0.202", + "ai-unwrapped": "npm:ai@6.0.202", + "cloudflare-think-v0": "npm:@cloudflare/think@0.13.0", + "cloudflare-think-v0-latest": "npm:@cloudflare/think@0.13.0", + "dc-browser": "1.0.4", + "vite": "7.3.1", + "wrangler": "4.112.0", + "zod": "4.3.6" + } +} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/pnpm-lock.yaml b/e2e/scenarios/cloudflare-think-instrumentation/pnpm-lock.yaml new file mode 100644 index 000000000..9eb51ca3a --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/pnpm-lock.yaml @@ -0,0 +1,4925 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@ai-sdk/openai': + specifier: 3.0.80 + version: 3.0.80(zod@4.3.6) + '@cloudflare/vite-plugin': + specifier: 1.45.1 + version: 1.45.1(vite@7.3.1(yaml@2.9.0))(wrangler@4.112.0) + agents: + specifier: 0.17.4 + version: 0.17.4(@babel/core@8.0.1)(@babel/runtime@7.29.7)(ai@6.0.202(zod@4.3.6))(chat@4.34.0(ai@6.0.202(zod@4.3.6))(zod@4.3.6))(just-bash@3.1.0)(react@19.2.7)(rolldown@1.2.0)(vite@7.3.1(yaml@2.9.0))(zod@4.3.6) + ai: + specifier: 6.0.202 + version: 6.0.202(zod@4.3.6) + ai-unwrapped: + specifier: npm:ai@6.0.202 + version: ai@6.0.202(zod@4.3.6) + cloudflare-think-v0: + specifier: npm:@cloudflare/think@0.13.0 + version: '@cloudflare/think@0.13.0(@ai-sdk/provider@3.0.14)(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(agents@0.17.4(@babel/core@8.0.1)(@babel/runtime@7.29.7)(ai@6.0.202(zod@4.3.6))(chat@4.34.0(ai@6.0.202(zod@4.3.6))(zod@4.3.6))(just-bash@3.1.0)(react@19.2.7)(rolldown@1.2.0)(vite@7.3.1(yaml@2.9.0))(zod@4.3.6))(ai@6.0.202(zod@4.3.6))(react@19.2.7)(vite@7.3.1(yaml@2.9.0))(zod@4.3.6)' + cloudflare-think-v0-latest: + specifier: npm:@cloudflare/think@0.13.0 + version: '@cloudflare/think@0.13.0(@ai-sdk/provider@3.0.14)(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(agents@0.17.4(@babel/core@8.0.1)(@babel/runtime@7.29.7)(ai@6.0.202(zod@4.3.6))(chat@4.34.0(ai@6.0.202(zod@4.3.6))(zod@4.3.6))(just-bash@3.1.0)(react@19.2.7)(rolldown@1.2.0)(vite@7.3.1(yaml@2.9.0))(zod@4.3.6))(ai@6.0.202(zod@4.3.6))(react@19.2.7)(vite@7.3.1(yaml@2.9.0))(zod@4.3.6)' + dc-browser: + specifier: 1.0.4 + version: 1.0.4 + vite: + specifier: 7.3.1 + version: 7.3.1(yaml@2.9.0) + wrangler: + specifier: 4.112.0 + version: 4.112.0 + zod: + specifier: 4.3.6 + version: 4.3.6 + +packages: + + '@ai-sdk/anthropic@3.0.98': + resolution: {integrity: sha512-JSHw0m15tXsdZWaV64UOjbHFKHGsPVUi9jYApNaz2QOBm987vl+l9aUFnlN1OWmFvDNMIhAPVOYRsFwjK0by/w==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/gateway@3.0.128': + resolution: {integrity: sha512-t9Dyqk5thSmIzsNvVTQtZZiO3xqKGkk1hX3+GNpYmro+GuEdW+E6mKFHihb9Y1vCEt3rEyd4pbGUcin4D57FfQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/openai@3.0.80': + resolution: {integrity: sha512-u3EfYbBG4YS/U2eOGH0yv8lPRwDj25X3sTluUKMYEwOLTZzWYv0IPtrpO7tPEra0QU4oq5Gpg49/FGFSrzE4vA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider-utils@4.0.28': + resolution: {integrity: sha512-nCtGJY43Kqwoyk0rYLj80a3eyXxcaWwyu+lYZDHgY+U6JbYYyvRdRTSy+XCDIB91rFH0Ul0eMDHmDr+YMYtrSw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider-utils@4.0.35': + resolution: {integrity: sha512-bjYld/2KGPLt78kpqbya+fD4LYS7BqVQJyUjE3qAHrYB0FR2Q90BaWEVIBZaguTWXf/A8L6uG1zO1v9TxVlGWg==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider-utils@4.0.40': + resolution: {integrity: sha512-OL5IrpUm9Y8Dwy+w/vvFwPotS6m52O9W0op2oXgXdCROMJIBalBI0oro6OIBYkPxvm5Xg02GSkoQN25RlR0bnw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider@3.0.10': + resolution: {integrity: sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw==} + engines: {node: '>=18'} + + '@ai-sdk/provider@3.0.13': + resolution: {integrity: sha512-ZPtVYt5QIJzOta1kdUiDuCx4HhFkvNPv/rvmZ2b1iXwybYjJsCnNYR4PAw4kW7rgVfDARvHXcU64efWuqNp6bw==} + engines: {node: '>=18'} + + '@ai-sdk/provider@3.0.14': + resolution: {integrity: sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA==} + engines: {node: '>=18'} + + '@babel/code-frame@8.0.0': + resolution: {integrity: sha512-dYYg153EyN2Ekbqw2zAsbd6/JR+9N2SEoC7YV2GyyqMM7x9bLDTjBD6XBhSMLH0wtIVyJj03jWNriQhaN+eoCw==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/compat-data@8.0.0': + resolution: {integrity: sha512-DOjnob/cXOUgDOozCDeq/aK2p5y8dUIVdf6tNhEV1HQRd6I8aQ4f4fbtHRVEvb6lP3BGomrKHiS8ICAASSVQSw==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/core@8.0.1': + resolution: {integrity: sha512-5FgxM4dLQpMJHSiVATk8foW263dVHQHBVpXYiimNECVWG01f4nFyEbQixeT6Mwvg7TayREJ2gpKl3o2RoMdnqw==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/generator@8.0.0': + resolution: {integrity: sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-annotate-as-pure@8.0.0': + resolution: {integrity: sha512-NSpMkMsvvZqzThJ0p1B02cbtA2ObEyfBvq950bmNkyxsxvcxwhvvCB036rKhlEnuBBo30bOrk13u3FzlKSoRrw==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-compilation-targets@8.0.0': + resolution: {integrity: sha512-JwculLABZvyPvyLBpwU/E/IbH2uM3mnxNtIJpxnIfb24y1PrdVxK5Dqjle4DpgqpGRnwgC7G8IkzPdSXZrO1Ew==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-create-class-features-plugin@8.0.1': + resolution: {integrity: sha512-++t3ZktzlLmASAxIlxeXQK9Z2YwUafYGYcvGBFevqOqt16HozVHStUoQvWD09fzAZOb/uJGpUTBuGK41AJAuOA==} + engines: {node: ^22.18.0 || >=24.11.0} + peerDependencies: + '@babel/core': ^8.0.0 + + '@babel/helper-globals@8.0.0': + resolution: {integrity: sha512-lLozHOM6sWWlxNo8CYqHy4MBZeTvHXNgVPBfPOGsjPKUzHC2Az9QwB6gxdQmpwHl6GlQtbGgS+lj5887guDiLw==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-member-expression-to-functions@8.0.0': + resolution: {integrity: sha512-xkXrMbtk87Gk7+oKBVmBc6EORg/Qwx++AHESldmHkpvG8wgccdhJJFwrzqlF382Fk8wfXhJHWE/g/43QvEGNPQ==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-optimise-call-expression@8.0.0': + resolution: {integrity: sha512-3W6satvtPuCUkUx63S2jMoW9EQNYkADgs1HTfufmL7gCmAulHMKupA/12WNz4A0GMMFn/YnWWwqOT9IZrJHQjg==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-plugin-utils@8.0.1': + resolution: {integrity: sha512-3PKFgjTyPlhFhorfP+SjKQxLViIL++zWjFOO4hGriYU+Bsm983DxEM1JmDRJVWXV0O9npu+xXRqz7Pbd3mh70g==} + engines: {node: ^22.18.0 || >=24.11.0} + peerDependencies: + '@babel/core': ^8.0.0 + + '@babel/helper-replace-supers@8.0.1': + resolution: {integrity: sha512-B1SZADIcy3tmH8CmWvj4SHi/oAPom4UL3uknTc2QRNsPVLFk/sPnZvQL/8kj7Y5omvjMqie0vklvs6XM4OLW5Q==} + engines: {node: ^22.18.0 || >=24.11.0} + peerDependencies: + '@babel/core': ^8.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@8.0.0': + resolution: {integrity: sha512-xmCA9kP3IhySsqhzwIdWGlDN/1A4cCKNBO/uwZx/3YzmDoMePwno2Q5/Bq0q+tYaKbeF940YiKV/kaW8Mzvpjw==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-string-parser@8.0.0': + resolution: {integrity: sha512-6mJgmFFFIIO82vvoLt9XtRC7/TkzXfts1t/SpRX4IHSzMgqoPYCWesVu1udUPUWioAE/2fcG6WuI8zrkE1gwrg==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-validator-identifier@8.0.4': + resolution: {integrity: sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helper-validator-option@8.0.0': + resolution: {integrity: sha512-U4Dybxh4WESWHt5XhBeExi4DrY0/DNK1aHpQbsrQXCUbFHuMweT0TpLEWKvaraV2Y6fS+ZXunsZ8zIuZIgvF2Q==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/helpers@8.0.0': + resolution: {integrity: sha512-wfbi91pM3py96oIiJEz7qIpyXDytgr9zQC1HEWwlGNVRAEmItuU/0a41ZUKu1sJGyhhOIpc4t5vk4PYzt8wpsg==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/parser@8.0.4': + resolution: {integrity: sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==} + engines: {node: ^22.18.0 || >=24.11.0} + hasBin: true + + '@babel/plugin-proposal-decorators@8.0.2': + resolution: {integrity: sha512-+C6O6KKXU7BBq1GNaIkFJxrALUVGRcr+WeWm4OcuRl3h+l/CmNfcTLMrT2Lm3uvGBimBH/8pEBRrXJFLoO67Gg==} + engines: {node: ^22.18.0 || >=24.11.0} + peerDependencies: + '@babel/core': ^8.0.0 + + '@babel/plugin-syntax-decorators@8.0.1': + resolution: {integrity: sha512-NI+0S/6MvR6GlcQFwjDZ+WIc2qvG6TXN534lYs9llNldwW4b7Dh6KTtk030FA0xWdYGs4t1lWo+OEWN8wGB+Nw==} + engines: {node: ^22.18.0 || >=24.11.0} + peerDependencies: + '@babel/core': ^8.0.0 + + '@babel/runtime-corejs3@7.29.7': + resolution: {integrity: sha512-ppj9ouYku+RX0ljtgZd+KMO5mkM2bCqg8H2PYAFWnLsHEIKIdRojqbJ2i3eVHrisuxy7nOFCmngTDdWtUCdXUQ==} + engines: {node: '>=6.9.0'} + + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} + engines: {node: '>=6.9.0'} + + '@babel/template@8.0.0': + resolution: {integrity: sha512-eAD0QW/AlbamBbw0FeGiwasbCVPq5ncW0HNVyLP3B9czqLyh4gvw+5JTSNt6le9+ziAU7mqDZsKTHf3jTb4chQ==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/traverse@8.0.4': + resolution: {integrity: sha512-bZnmqzGG8UZneG1lLxBoWIH0G6Gr1D846Yu4/3XnY6FhCndMR49u26nTY08u/dAxWmLWF9vGQOuC+84FfIUoeg==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@babel/types@8.0.4': + resolution: {integrity: sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==} + engines: {node: ^22.18.0 || >=24.11.0} + + '@borewit/text-codec@0.2.2': + resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} + + '@cfworker/json-schema@4.1.1': + resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} + + '@cloudflare/codemode@0.4.3': + resolution: {integrity: sha512-S6LIqj/NnmFRFxm3j0tPEGMF8HQF5DpV7sQg/W+U48YmnznTKOBcbS8eiV7SxBpIITLuMBcL4KpTDm1RDL20pA==} + peerDependencies: + '@modelcontextprotocol/sdk': ^1.25.0 + '@tanstack/ai': '>=0.8.0 <1.0.0' + ai: ^6.0.0 + zod: ^4.0.0 + peerDependenciesMeta: + '@modelcontextprotocol/sdk': + optional: true + '@tanstack/ai': + optional: true + ai: + optional: true + zod: + optional: true + + '@cloudflare/kv-asset-handler@0.5.0': + resolution: {integrity: sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==} + engines: {node: '>=22.0.0'} + + '@cloudflare/shell@0.4.1': + resolution: {integrity: sha512-fOj7W6LJOPUppTxJ8JYSj5umEZtwz0Lf7dGYXjiRPBEtSjoASnJfMpfNqitLLeDC5qx0VIzaa/6oskMWQvUOTw==} + + '@cloudflare/think@0.13.0': + resolution: {integrity: sha512-0Zo7jjPLLUv2q4FRu9ww3GrDFCOv73NgDl19yfjVGcYzAnxphiWRNaG1Sl7bwXcfWKZBUZ4SE2ckT3WEUjqzzw==} + hasBin: true + peerDependencies: + '@ai-sdk/react': ^3.0.204 + '@chat-adapter/telegram': ^4.29.0 + agents: '>=0.17.1 <1.0.0' + ai: ^6.0.182 + react: ^19.0.0 + vite: '>=6 <9' + zod: ^4.0.0 + peerDependenciesMeta: + '@ai-sdk/react': + optional: true + '@chat-adapter/telegram': + optional: true + react: + optional: true + vite: + optional: true + + '@cloudflare/unenv-preset@2.16.1': + resolution: {integrity: sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==} + peerDependencies: + unenv: 2.0.0-rc.24 + workerd: '>1.20260305.0 <2.0.0-0' + peerDependenciesMeta: + workerd: + optional: true + + '@cloudflare/vite-plugin@1.45.1': + resolution: {integrity: sha512-C+iDpO9pVH7IqrjdYtUV+obcTAdpiNk0OSinGEZZyd2ZWyGVjGk7iJ2p3xpMBpZuTa1I4hfAECNp0yN/8f3PIQ==} + hasBin: true + peerDependencies: + vite: ^6.1.0 || ^7.0.0 || ^8.0.0 + wrangler: ^4.112.0 + + '@cloudflare/workerd-darwin-64@1.20260714.1': + resolution: {integrity: sha512-ZWXqAN8G7Cx9hMRQuk+59ziJhR3j1F4iO+Qs8aHdfKZ3Dq5Yi/57xvkJTgCGBnW1YU/L78r8f6HEy51bwbTpNw==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + + '@cloudflare/workerd-darwin-arm64@1.20260714.1': + resolution: {integrity: sha512-tueWxWC3wyCbMG6zRAxsMXX0YLgrRWbiAPYFQ2uJ7dUH8G+5E7UTWaQS9B1HdJ0bpKFW1NWxhs1o2noKVFSUYg==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + + '@cloudflare/workerd-linux-64@1.20260714.1': + resolution: {integrity: sha512-1VChTZRb0l0F7R4e1G5RtLKV4oFi6x+rQgxh2+yu887j3l/3TLgatuv1L8/5zhc9gKEhATTxOh0e52Rtd9dDWQ==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + + '@cloudflare/workerd-linux-arm64@1.20260714.1': + resolution: {integrity: sha512-rMm3G+NirG2UdgHIRDdF1asNC6FqgIzZzkRG+VDhhDGcVxAQwvrMT1E38BivEvHr3G04MB4AfhcOczX0+GtRkQ==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + + '@cloudflare/workerd-windows-64@1.20260714.1': + resolution: {integrity: sha512-cGqnU3Hg2YZS/k3SAqrMp1DjpdsyFde72tWltdl6ZT9+SFz/Zrk/8gyTU1TcxC4YApXeNVH5TyU5cOGPgUJ0pg==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@emnapi/core@1.11.2': + resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} + + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} + + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@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.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.28.1': + resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.28.1': + resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + engines: {node: '>=18'} + cpu: [x64] + 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.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.28.1': + resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.28.1': + resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@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.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + engines: {node: '>=18'} + cpu: [x64] + 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.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.28.1': + resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + engines: {node: '>=18'} + cpu: [arm] + 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.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + engines: {node: '>=18'} + cpu: [ia32] + 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.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + engines: {node: '>=18'} + cpu: [loong64] + 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.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.28.1': + resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + engines: {node: '>=18'} + cpu: [ppc64] + 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.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.28.1': + resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + engines: {node: '>=18'} + cpu: [s390x] + 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.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + engines: {node: '>=18'} + cpu: [x64] + 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.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-arm64@0.28.1': + resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.28.1': + resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-arm64@0.28.1': + resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + engines: {node: '>=18'} + cpu: [x64] + 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.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/openharmony-arm64@0.28.1': + resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.28.1': + resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.28.1': + resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + engines: {node: '>=18'} + cpu: [ia32] + 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.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.28.1': + resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@hono/node-server@1.19.14': + resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} + engines: {node: '>=18.14.1'} + peerDependencies: + hono: ^4 + + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.5': + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.5': + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.4': + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.4': + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.2.4': + resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-arm@1.2.4': + resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-ppc64@1.2.4': + resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-riscv64@1.2.4': + resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-s390x@1.2.4': + resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-x64@1.2.4': + resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-linux-arm64@0.34.5': + resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-arm@0.34.5': + resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-ppc64@0.34.5': + resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-riscv64@0.34.5': + resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-s390x@0.34.5': + resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-x64@0.34.5': + resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-linuxmusl-arm64@0.34.5': + resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-linuxmusl-x64@0.34.5': + resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-wasm32@0.34.5': + resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.5': + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.5': + resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.5': + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@jitl/quickjs-ffi-types@0.32.0': + resolution: {integrity: sha512-v9T+GQpmk43VDJ7d72sf0Nexhk+ArvtUihW27dy7lqAl0zBObFKtSBBIm5RBjwIhE8VwsPPm9PNuvPvNqLWUEg==} + + '@jitl/quickjs-wasmfile-debug-asyncify@0.32.0': + resolution: {integrity: sha512-EX8zbXwGqCgAE764M+qvkHtyXDi/FUoMBea0JnES7vCM3P7a2+EOZOjGv85wtZ2sJhI1oJ+nekmqpOODFDY+hw==} + + '@jitl/quickjs-wasmfile-debug-sync@0.32.0': + resolution: {integrity: sha512-LeYWrPGC1uNCTBWvibo3ZLJj0CSVNYUXvJpXMCmuQ5Sap2cCACc3uvGvYV4homHHBAzfw5akoTqMMS4YFRtw+Q==} + + '@jitl/quickjs-wasmfile-release-asyncify@0.32.0': + resolution: {integrity: sha512-3oSwPfja12ICz4aIblB58cuY8JlEq5Txt8Cut4VLo+LH47QN+mzCnSgnbB03hWzg1LBcc+VyyI9UOag7a1NF+Q==} + + '@jitl/quickjs-wasmfile-release-sync@0.32.0': + resolution: {integrity: sha512-BKNDI/TPBfGlLNGYpLrhcDGXmIk4xHm4MRAisOBnOzpXVn9HZWsfmMAc9WMBrAHjvvds6HOikKeaOBKdPdpVrg==} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@mixmark-io/domino@2.2.0': + resolution: {integrity: sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==} + + '@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 + + '@mongodb-js/zstd@7.0.0': + resolution: {integrity: sha512-mQ2s0pYYiav+tzCDR05Zptem8Ey2v8s11lri5RKGhTtL4COVCvVCk5vtyRYNT+9L8qSfyOqqefF9UtnW8mC5jA==} + engines: {node: '>= 20.19.0'} + + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@nodable/entities@3.0.0': + resolution: {integrity: sha512-8L9xFeTYKhm49xfIypoe2W5wV1m/3Z58kT+7kR9A8OyFxcPduI4VmxaUMQyKYrRjUoLLSXv6EKKID5Tvj9cUVw==} + + '@opentelemetry/api@1.9.1': + resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} + engines: {node: '>=8.0.0'} + + '@oxc-project/types@0.140.0': + resolution: {integrity: sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ==} + + '@poppinss/colors@4.1.6': + resolution: {integrity: sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==} + + '@poppinss/dumper@0.6.5': + resolution: {integrity: sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==} + + '@poppinss/exception@1.2.3': + resolution: {integrity: sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==} + + '@rolldown/binding-android-arm64@1.2.0': + resolution: {integrity: sha512-9yB1l95IrJuNGDFdOYe79vdApdz6WWBCObE+rQ2LUliYUlcyFwSYIb2xb5/Ifw7dAtMy2ZqNyd8QTSOc7duAKw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.2.0': + resolution: {integrity: sha512-pexNaW9ACLUOaBITOpU6qVu4VrsOFIjTv6bzgu0YUATo4eUJx0V605PxwZfndpPOn0ilqGqvGQ0M8UW0IE24jg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.2.0': + resolution: {integrity: sha512-NqKYaq0355ZmNMG4QGpxtEDxsc7tGDhjhCm4PpE0cwnBW+5Il95LJyq414niEiaKLVjnVHBEjSo1wngKxJNiFw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.2.0': + resolution: {integrity: sha512-3vPoHzh6eBTz9IbB0/qZdSr0Qeks2echn+I4cHu2joV74VriPDdldswksEDzrl1mBB+oPRi+67+3Ib59paxIPQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.2.0': + resolution: {integrity: sha512-E6NNefZ1bUVmKJq2tJkf45J4Zyczj7qm9rUT7NY+Xo2474Y13qWAwc2tvBt0BAVbmtXR1llkxXg0Ou1jbDf2SQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.2.0': + resolution: {integrity: sha512-D+TgkdgM1vu+7/Fpf8+v0ARW+RXEP9Ccazgm8zQ4JFFd9Q7SrYQ2TakU5S5ihazQDgpKyAgZDOcIFsvoHmTZ8w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.2.0': + resolution: {integrity: sha512-wUqdwJBbAv0APN87GecstdMUtLjjNTs0hBALpxETD73mccFxdmt/XeizXDtN5RAlBwNKmI+Tg+blect2G+8IeQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.2.0': + resolution: {integrity: sha512-9DtF35qR9/NrfhM4oxLplCzVVjE+KKm8Pjemi0i/sdhAWkUasjmSo8WTTubNJClhSHCfyk2yeyoXDQEDPtDAAw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.2.0': + resolution: {integrity: sha512-RzuHrBh8X8Hntd2N4VR02QGEciq/9JhcZoTpR/Cee6otRrlILGCf3cg2ygHuih+ZebUnWmMrDX6ITI85btO6rQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.2.0': + resolution: {integrity: sha512-MK7L0018jjh1jR3mh21G2j1zAVcpscJBlPo2z19pRjv2XOYGRhaV4LyiD8HO6nCDdZln9IFgCMIV5yt4E3klGQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.2.0': + resolution: {integrity: sha512-gyrxLQ9NfGb/9LoVnC4kb9miUghw1mghnkfYvNHSnVIXriabnfgGPUP4RLcJm87q3KgYz4FYUG8IDiWUT+CpSw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.2.0': + resolution: {integrity: sha512-/6VFMQGRmrhP77KXDC+StIxGzcNp5JOIyYtw0CQ8gPlzhpiIRucYfoM5FaFamHd5BJYIdH86yfP46l1p3WdrFA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.2.0': + resolution: {integrity: sha512-rwdbUL465kisF24WEJLvP3JrEG6E5GRuIHt5wpMwHGERtHe4Wm2CIvtf5gTBgr2tGOHKh5NdKEAFS2VkOPE91g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.2.0': + resolution: {integrity: sha512-+5suHwRiKGmhwyUaNT8a5QbrBvLFh2DbO910TEmGRH1aSxwrCezodvGQnulv4uiWEIv1Kq4ypRsJ5+O+ry1DiA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.2.0': + resolution: {integrity: sha512-WfFv6/qGufotqBSBzBYwgpCkJBk8Nj7697LL9vTz/XWc67e0r3oewu8iMRwQj3AUL45GVD7wVsPjCsAAtW66Wg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/plugin-babel@0.2.3': + resolution: {integrity: sha512-+zEk16yGlz1F9STiRr6uG9hmIXb6nprjLczV/htGptYuLoCuxb+itZ03RKCEeOhBpDDd1NU7qF6x1VLMUp62bw==} + engines: {node: '>=22.12.0 || ^24.0.0'} + peerDependencies: + '@babel/core': ^7.29.0 || ^8.0.0-rc.1 + '@babel/plugin-transform-runtime': ^7.29.0 || ^8.0.0-rc.1 + '@babel/runtime': ^7.27.0 || ^8.0.0-rc.1 + rolldown: ^1.0.0-rc.5 + vite: ^8.0.0 + peerDependenciesMeta: + '@babel/plugin-transform-runtime': + optional: true + '@babel/runtime': + optional: true + vite: + optional: true + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@rollup/rollup-android-arm-eabi@4.62.2': + resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.62.2': + resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.62.2': + resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.62.2': + resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.62.2': + resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.62.2': + resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.62.2': + resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.62.2': + resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.62.2': + resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.62.2': + resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.62.2': + resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.62.2': + resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.62.2': + resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.62.2': + resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.62.2': + resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.62.2': + resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.62.2': + resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.62.2': + resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.62.2': + resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.62.2': + resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.62.2': + resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} + cpu: [x64] + os: [win32] + + '@sindresorhus/is@7.2.0': + resolution: {integrity: sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==} + engines: {node: '>=18'} + + '@speed-highlight/core@1.2.17': + resolution: {integrity: sha512-Z92FwKpCtfaW1V0jTU/fh3QzYEZN8wDwrzRIBoADCJfn4mJCNcJN/XegifX7BDrQ8/h9Xh/JnbyMchL0FqXrkg==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@tokenizer/inflate@0.4.1': + resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} + engines: {node: '>=18'} + + '@tokenizer/token@0.3.0': + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + + '@types/debug@4.1.13': + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/gensync@1.0.5': + resolution: {integrity: sha512-MbsRCT7mTikHwKZ0X+LVUTLRrZZRLipTuXEO9qOYO+zmjMVk81axyClMROf6uoPD9MRVu46bx8zoR0Ad9q3NAg==} + + '@types/jsesc@2.5.1': + resolution: {integrity: sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@vercel/oidc@3.2.0': + resolution: {integrity: sha512-UycprH3T6n3jH0k44NHMa7pnFHGu/N05MjojYr+Mc6I7obkoLIJujSWwin1pCvdy/eOxrI/l3uDLQsmcrOb4ug==} + engines: {node: '>= 20'} + + '@workflow/serde@4.1.0-beta.2': + resolution: {integrity: sha512-8kkeoQKLDaKXefjV5dbhBj2aErfKp1Mc4pb6tj8144cF+Em5SPbyMbyLCHp+BVrFfFVCBluCtMx+jjvaFVZGww==} + + 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'} + + acorn@8.17.0: + resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + engines: {node: '>=0.4.0'} + hasBin: true + + agents@0.17.4: + resolution: {integrity: sha512-K6YRbpD3VcwdTOPBlDgI4dILAwkhXo5cdxTlVF0IvUwQEKfMPawmH8E/QMXTN8CPGHqVYgYFACxTyk6nKlK+vg==} + hasBin: true + peerDependencies: + '@ai-sdk/react': ^3.0.204 + '@tanstack/ai': '>=0.10.2 <1.0.0' + '@x402/core': ^2.0.0 + '@x402/evm': ^2.0.0 + ai: ^6.0.0 + chat: ^4.29.0 + just-bash: ^3.0.0 + react: ^19.0.0 + vite: '>=6.0.0 <9.0.0' + zod: ^4.0.0 + peerDependenciesMeta: + '@ai-sdk/react': + optional: true + '@tanstack/ai': + optional: true + '@x402/core': + optional: true + '@x402/evm': + optional: true + ai: + optional: true + chat: + optional: true + just-bash: + optional: true + vite: + optional: true + + ai@6.0.202: + resolution: {integrity: sha512-14O7uyHVa5lXyt1RzduRqM1zwOnLBN+EaE+btWiP2R7GLHd5oh+Z9uaebR785V/Y2hXlxvuQGsw2Gj6iHpkxsg==} + 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==} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + anynum@1.0.1: + resolution: {integrity: sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==} + + async-lock@1.4.1: + resolution: {integrity: sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + aywson@0.0.16: + resolution: {integrity: sha512-xLFICM6OgSMcysNHCgrhri7hpcn0TfuyU5KxtjpIAJAUuD0Bjph2pSkLgxjn45iQBjBxs4S5Fq+RmXhIYuQtNw==} + hasBin: true + + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + baseline-browser-mapping@2.10.43: + resolution: {integrity: sha512-AjYpR78kDWAY3Efj+cDTFH9t9SCoL7OoTp1BOb0mQV7S+6CiLwnWM3FyxhJtdPufDFKzmCSFoUncKjWgJEZTCQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + blake3-wasm@2.1.5: + resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} + + body-parser@2.3.0: + resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} + engines: {node: '>=18'} + + brace-expansion@5.0.7: + resolution: {integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==} + engines: {node: 18 || 20 || >=22} + + browserslist@4.28.6: + resolution: {integrity: sha512-FQBYNK15VMslhLHpA7+n+n1GOlF1kId2xcCg7/j95f24AOF6VDYMNH4mFxF7KuaTdv627faazpOAjFzMrfJOUw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + 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-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + caniuse-lite@1.0.30001806: + resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + chat@4.34.0: + resolution: {integrity: sha512-g3c9ANavtCX7BwHcB5c3lWKIUm+8Oo7qlbgQ7/ni1rmVLLeCQa7FiMfeIyEyTAd/4HlRQu5jcS4EPdb0VyhUDQ==} + engines: {node: '>=20'} + peerDependencies: + ai: ^6.0.182 || ^7.0.0 + zod: ^3.0.0 || ^4.0.0 + peerDependenciesMeta: + ai: + optional: true + zod: + optional: true + + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + + clean-git-ref@2.0.1: + resolution: {integrity: sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==} + + cliui@9.0.1: + resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} + engines: {node: '>=20'} + + commander@6.2.1: + resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} + engines: {node: '>= 6'} + + 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'} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + 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'} + + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + + core-js-pure@3.49.0: + resolution: {integrity: sha512-XM4RFka59xATyJv/cS3O3Kml72hQXUeGRuuTmMYFxwzc9/7C8OYTaIR/Ji+Yt8DXzsFLNhat15cE/JP15HrCgw==} + + cors@2.8.6: + resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} + engines: {node: '>= 0.10'} + + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + create-think@0.1.1: + resolution: {integrity: sha512-C8+k9fPArd1B0nnDUV83Fjw7hzJyaY+LN4v3Va+k4enMlSw0ZvyJERjJwntcp+1Snos+sy07SQYpV+1k10zARQ==} + hasBin: true + + cron-schedule@6.0.0: + resolution: {integrity: sha512-BoZaseYGXOo5j5HUwTaegIog3JJbuH4BbrY9A1ArLjXpy+RWb3mV28F/9Gv1dDA7E2L8kngWva4NWisnLTyfgQ==} + engines: {node: '>=20'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + dc-browser@1.0.4: + resolution: {integrity: sha512-7oEtnzNlcE+hr4OvO3GR6Gndgw8BhW+wKOEwMqSleyY7N29jbAxzyW5BaJl7qBCw+6OIxfMWtY0T+6dxq8RWLw==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-named-character-reference@1.3.0: + resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + diff3@0.0.3: + resolution: {integrity: sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==} + + diff@8.0.4: + resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} + engines: {node: '>=0.3.1'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + electron-to-chromium@1.5.393: + resolution: {integrity: sha512-kiDJdIUawuEIcp9XoICKp1iTYDEbgguIPq526N1Q7jIQDeQ3CqoMx71025PI/7E48Ddtw2HuWsVjY7afEgNxmg==} + + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + + empathic@2.0.1: + resolution: {integrity: sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q==} + engines: {node: '>=14'} + + 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==} + + error-stack-parser-es@1.0.5: + resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==} + + 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'} + + esbuild@0.27.7: + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + engines: {node: '>=18'} + hasBin: true + + esbuild@0.28.1: + resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-polyfill@0.0.4: + resolution: {integrity: sha512-Gs6RLjzlLRdT8X9ZipJdIZI/Y6/HhRLyq9RdDlCsnpxr/+Nn6bU2EFGuC94GjxqhM+Nmij2Vcq98yoHrU8uNFQ==} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + 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'} + + expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + + express-rate-limit@8.6.0: + resolution: {integrity: sha512-XKJXDsASUOo0LLtFwW5hCcQGH0N4WQc/Rn8/Pvoia+TJFOkkFPvrtW9lZOeeNcxQJspvOIERMwiRLsVFlhHEkA==} + 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-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-uri@3.1.4: + resolution: {integrity: sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==} + + fast-xml-builder@1.3.0: + resolution: {integrity: sha512-F74cZEdCvuw9P41GAC3rod4X04jjWGM1JPEv/GWSqFTWLsdyMSBMBMlm9Hk3GLBgLBbdBNY8yee0pQh2RBVESQ==} + + fast-xml-parser@5.10.1: + resolution: {integrity: sha512-IEMIf7298kXuZSRFoGfMYrl7is8LpavODgbNz1cwIudv7KwVFnuU+UsMporfq6PD6aXSlawZlARiA3UywCTfMw==} + hasBin: true + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-type@21.3.4: + resolution: {integrity: sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==} + engines: {node: '>=20'} + + finalhandler@2.1.1: + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + 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'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + 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==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.6.0: + resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} + 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'} + + github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + 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'} + + hono@4.12.31: + resolution: {integrity: sha512-zJIHFrl6bq3RDd2YusFNCDlM8qUprxKswyi/OPzPyzKDdyBXDqWx8bZlZ7R+saTdSTatUmb3O7K4SspGPaEOQg==} + engines: {node: '>=16.9.0'} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + iconv-lite@0.7.3: + resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + ini@6.0.0: + resolution: {integrity: sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==} + engines: {node: ^20.17.0 || >=22.9.0} + + 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-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-unsafe@2.0.0: + resolution: {integrity: sha512-2LdV822R+wmI86unXA93WCFpL6g+av8ynWk0nrHyJqGop5VoocYsSLFgN8jrfalT6iGeLNM4KXuVSsULP53kEA==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isomorphic-git@1.38.9: + resolution: {integrity: sha512-3nwGo1UIScJUW2/W4KzTGA/V7Bf/AivBF4KuZGfxU+Bcz2oJo2emuxJK8hP2saZ3XfLOBqbKs+x9CLsFrn8vAg==} + engines: {node: '>=14.17'} + hasBin: true + + jose@6.2.3: + resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} + + js-base64@3.9.1: + resolution: {integrity: sha512-U73qptcvf/HIOauFOmqT3a0mDUp0MYlfd15oqoe9kqZt5XhiXVb+HG09sLvI9PQ9tZIBFS4nlErai8zbWazP0g==} + + js-tokens@10.0.0: + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + 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==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + + just-bash@3.1.0: + resolution: {integrity: sha512-/t28X8EH3+j/zvELGkNhlFV2g6hc3oHBzy6zPBnNq2nqUN0DGS9PsD889JfQ7F6ll08gqFoutiS+VJHK30wZpg==} + hasBin: true + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} + engines: {node: 20 || >=22} + + markdown-table@3.0.4: + resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdast-util-find-and-replace@3.0.2: + resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} + + mdast-util-from-markdown@2.0.3: + resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==} + + mdast-util-gfm-autolink-literal@2.0.1: + resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} + + mdast-util-gfm-footnote@2.1.0: + resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==} + + mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + + mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + + mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + + mdast-util-gfm@3.1.0: + resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-markdown@2.1.2: + resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + 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'} + + micromark-core-commonmark@2.0.3: + resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + + micromark-extension-gfm-autolink-literal@2.1.0: + resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} + + micromark-extension-gfm-footnote@2.1.0: + resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} + + micromark-extension-gfm-strikethrough@2.1.0: + resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} + + micromark-extension-gfm-table@2.1.1: + resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} + + micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + + micromark-extension-gfm-task-list-item@2.1.0: + resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} + + micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-subtokenize@2.1.0: + resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + + micromark@4.0.2: + resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} + + 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'} + + mimetext@3.0.28: + resolution: {integrity: sha512-eQXpbNrtxLCjUtiVbR/qR09dbPgZ2o+KR1uA7QKqGhbn8QV7HIL16mXXsobBL4/8TqoYh1us31kfz+dNfCev9g==} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + miniflare@4.20260714.0: + resolution: {integrity: sha512-MYlTCLdWCPqvrYY2uLwOjXwmglXuiHE3TGGkbOW4BwjUPa1r07E0iuHwrNDIs/sxK21r+o90Jx58AV2KeNdJZw==} + engines: {node: '>=22.0.0'} + hasBin: true + + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minimisted@2.0.1: + resolution: {integrity: sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==} + + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + + modern-tar@0.7.7: + resolution: {integrity: sha512-t9VmxaqrmANnEOBhpSDI6HD192Ge48k8vmWqQQL7hSFEqHEYwZbbsu49+aKLWZeRvFs3j1pMhXOqqF4kPlvjkQ==} + engines: {node: '>=18.0.0'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.16: + resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.1.16: + resolution: {integrity: sha512-kVrnsrJqMR8+oLJnGEmSWw9BivK5mt7H3FZatVRjrc5wGqFYuBxX1yG7+A7Gi5AefkX6t/oCkizcQgpu0cY1dQ==} + engines: {node: ^18 || >=20} + hasBin: true + + napi-build-utils@2.0.0: + resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} + + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + + node-abi@3.94.0: + resolution: {integrity: sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==} + engines: {node: '>=10'} + + node-addon-api@8.9.0: + resolution: {integrity: sha512-ekZMeaaIzSQTSpr7X2X3iJM7lTzgnx8ahAG9pJfT/7+14mlEM8ZYQ9cgCDvSSRbReFK0oHli3WrZdCiRsgAT9Q==} + engines: {node: ^18 || ^20 || >= 21} + + node-gyp-build@4.8.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + hasBin: true + + node-liblzma@2.2.0: + resolution: {integrity: sha512-s0KzNOWwOJJgPG6wxg6cKohnAl9Wk/oW1KrQaVzJBjQwVcUGPQCzpR46Ximygjqj/3KhOrtJXnYMp/xYAXp75g==} + engines: {node: '>=16.0.0'} + hasBin: true + + node-releases@2.0.51: + resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} + engines: {node: '>=18'} + + 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'} + + obug@2.1.4: + resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} + engines: {node: '>=12.20.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==} + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + + papaparse@5.5.4: + resolution: {integrity: sha512-SwzWD9gl/ElwYLCI0nUja1mFJzjq2D8ziShfNBa7zCHzkOozeOGDwHWQ+tvCzEZcewecWZ5U7kUopDnG+DFYEQ==} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + partyserver@0.5.8: + resolution: {integrity: sha512-htgSwiBcBu9zIYLrsxBAOvdkjukHvncbTk0nDrJgfruvZ08rxtEN1Ab4T7j9osykP80Bq3zA2oWFd3ngc4Z9uw==} + peerDependencies: + '@cloudflare/workers-types': ^4.20260424.1 + + partysocket@1.3.0: + resolution: {integrity: sha512-1zToNyolZFK/7nuAw/K2bZrNzFqaZyRoCEkS+9vG6WSC5ikrN6qWRe96q6ImU51uptz2r+dAwSkwhJVdQi4LiA==} + peerDependencies: + react: '>=17' + peerDependenciesMeta: + react: + optional: true + + path-expression-matcher@1.6.2: + resolution: {integrity: sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==} + engines: {node: '>=14.0.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + + path-to-regexp@8.4.2: + resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pkce-challenge@5.0.1: + resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} + engines: {node: '>=16.20.0'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss@8.5.20: + resolution: {integrity: sha512-lW616l85ucIQL+FocMmL7pQFPqBmwejrCMg+iPxyImlrANNJG9NHq/RkyCZopDhd8C3LA03PHRJDjkbGu8vvug==} + engines: {node: ^10 || ^12 || >=14} + + prebuild-install@7.1.3: + resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} + engines: {node: '>=10'} + deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available. + hasBin: true + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.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.3: + resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} + engines: {node: '>=0.6'} + + quickjs-emscripten-core@0.32.0: + resolution: {integrity: sha512-QFnPfjFey8EqknSrSxe1hZrf1/8z7/6s1QzGOmKo6++02r7QRRX7ZoyNaZh7JuVjWsVW87KnQrbZqnHkOAzUyg==} + + quickjs-emscripten@0.32.0: + resolution: {integrity: sha512-So0Sqw869y/S2oE3Nuc0uT3Dhqgvsj8FSrwBdsuTosVsG8ME5/OcudU1GxsrIFdFABgy17GHnTVO9TYV/bLQcA==} + engines: {node: '>=16.0.0'} + + range-parser@1.3.0: + resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==} + engines: {node: '>= 0.6'} + + raw-body@3.0.2: + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} + engines: {node: '>= 0.10'} + + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + re2js@1.3.3: + resolution: {integrity: sha512-s/I5zEAo79SUK0Qw4dpZKpiMwbQ6Gz0KU2NRr7eaO4x/p2g7Vvmn3hdeXDg8VsaUjfj/ora+e9oi27LX/C9+mw==} + + react@19.2.7: + resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} + engines: {node: '>=0.10.0'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + remark-gfm@4.0.1: + resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} + + remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + + remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + + remend@1.3.0: + resolution: {integrity: sha512-iIhggPkhW3hFImKtB10w0dz4EZbs28mV/dmbcYVonWEJ6UGHHpP+bFZnTh6GNWJONg5m+U56JrL+8IxZRdgWjw==} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + rolldown@1.2.0: + resolution: {integrity: sha512-u7tgm5l4Yw1iTqUL4EcYOAt7fFvCgQMLeidrnD4GALlC6aOznCjezYajgxeyKw27u0Q5N7fwgCzjVyPIWzwuBA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rollup@4.62.2: + resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + 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==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + seek-bzip@2.0.0: + resolution: {integrity: sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==} + hasBin: true + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + 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-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + sha.js@2.4.12: + resolution: {integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==} + engines: {node: '>= 0.10'} + hasBin: true + + sharp@0.34.5: + resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + 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'} + + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + + smol-toml@1.7.0: + resolution: {integrity: sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==} + engines: {node: '>= 18'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + sql.js@1.14.1: + resolution: {integrity: sha512-gcj8zBWU5cFsi9WUP+4bFNXAyF1iRpA3LLyS/DP5xlrNzGmPIizUeBggKa8DbDwdqaKwUcTEnChtd2grWo/x/A==} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + strnum@2.4.1: + resolution: {integrity: sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg==} + + strtok3@10.3.5: + resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==} + engines: {node: '>=18'} + + supports-color@10.2.2: + resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} + engines: {node: '>=18'} + + tar-fs@2.1.5: + resolution: {integrity: sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + to-buffer@1.2.2: + resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} + engines: {node: '>= 0.4'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + token-types@6.1.2: + resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} + engines: {node: '>=14.16'} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + + turndown@7.2.4: + resolution: {integrity: sha512-I8yFsfRzmzK0WV1pNNOA4A7y4RDfFxPRxb3t+e3ui14qSGOxGtiSP6GjeX+Y6CHb7HYaFj7ECUD7VE5kQMZWGQ==} + engines: {node: '>=18', npm: '>=9'} + + type-is@2.1.0: + resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} + engines: {node: '>= 18'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + uint8array-extras@1.5.0: + resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} + engines: {node: '>=18'} + + undici@7.28.0: + resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} + engines: {node: '>=20.18.1'} + + unenv@2.0.0-rc.24: + resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} + + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite@7.3.1: + resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + which-typed-array@1.1.22: + resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + workerd@1.20260714.1: + resolution: {integrity: sha512-oIbQzfdyl9UQUnG6XLegcSq0Mgt/7WKDbFOoqGgOWCS+/fhyGB460uKEgdAQQ9RHCO/ttcNCX/KiMIQzdoeu3Q==} + engines: {node: '>=16'} + hasBin: true + + workers-ai-provider@3.3.1: + resolution: {integrity: sha512-vArwnmiAxQQF1clsXJd9ADn1xK9YUZVxE4umaMhrdsxM2kucxP430LfaoH4rn0AfoqtnuH3bfRhW1ak0r1x/8A==} + peerDependencies: + '@ai-sdk/anthropic': ^3.0.0 + '@ai-sdk/google': ^3.0.0 + '@ai-sdk/openai': ^3.0.0 + '@ai-sdk/provider': ^3.0.0 + ai: ^6.0.0 + peerDependenciesMeta: + '@ai-sdk/anthropic': + optional: true + '@ai-sdk/google': + optional: true + '@ai-sdk/openai': + optional: true + + wrangler@4.112.0: + resolution: {integrity: sha512-5H+XUD0TySCv1LuktFHDIEOkboH2nTfQs+35L+USt3MtntjDTMVIJprLgQcL2WBjulOyjxpd1vyTiSTJVW5MjQ==} + engines: {node: '>=22.0.0'} + hasBin: true + peerDependencies: + '@cloudflare/workers-types': ^5.20260714.1 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + + 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 + + xml-naming@0.3.0: + resolution: {integrity: sha512-ghig2TBE/H11aOVgmahA3MhimvkBr6JIYknH/Dhdk10nXwdbIqBJsbfMxpvFPG8bAw77gN29aQWvKpmVoPlvPQ==} + engines: {node: '>=16.0.0'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@22.0.0: + resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + yargs@18.0.0: + resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + youch-core@0.3.3: + resolution: {integrity: sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==} + + youch@4.1.0-beta.10: + resolution: {integrity: sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==} + + zod-to-json-schema@3.25.2: + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + peerDependencies: + zod: ^3.25.28 || ^4 + + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@ai-sdk/anthropic@3.0.98(zod@4.3.6)': + dependencies: + '@ai-sdk/provider': 3.0.14 + '@ai-sdk/provider-utils': 4.0.40(zod@4.3.6) + zod: 4.3.6 + + '@ai-sdk/gateway@3.0.128(zod@4.3.6)': + dependencies: + '@ai-sdk/provider': 3.0.10 + '@ai-sdk/provider-utils': 4.0.28(zod@4.3.6) + '@vercel/oidc': 3.2.0 + zod: 4.3.6 + + '@ai-sdk/openai@3.0.80(zod@4.3.6)': + dependencies: + '@ai-sdk/provider': 3.0.13 + '@ai-sdk/provider-utils': 4.0.35(zod@4.3.6) + zod: 4.3.6 + + '@ai-sdk/provider-utils@4.0.28(zod@4.3.6)': + dependencies: + '@ai-sdk/provider': 3.0.10 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.1.0 + zod: 4.3.6 + + '@ai-sdk/provider-utils@4.0.35(zod@4.3.6)': + dependencies: + '@ai-sdk/provider': 3.0.13 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.1.0 + zod: 4.3.6 + + '@ai-sdk/provider-utils@4.0.40(zod@4.3.6)': + dependencies: + '@ai-sdk/provider': 3.0.14 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.1.0 + zod: 4.3.6 + + '@ai-sdk/provider@3.0.10': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/provider@3.0.13': + dependencies: + json-schema: 0.4.0 + + '@ai-sdk/provider@3.0.14': + dependencies: + json-schema: 0.4.0 + + '@babel/code-frame@8.0.0': + dependencies: + '@babel/helper-validator-identifier': 8.0.4 + js-tokens: 10.0.0 + + '@babel/compat-data@8.0.0': {} + + '@babel/core@8.0.1': + dependencies: + '@babel/code-frame': 8.0.0 + '@babel/generator': 8.0.0 + '@babel/helper-compilation-targets': 8.0.0 + '@babel/helpers': 8.0.0 + '@babel/parser': 8.0.4 + '@babel/template': 8.0.0 + '@babel/traverse': 8.0.4 + '@babel/types': 8.0.4 + '@types/gensync': 1.0.5 + convert-source-map: 2.0.0 + empathic: 2.0.1 + gensync: 1.0.0-beta.2 + import-meta-resolve: 4.2.0 + json5: 2.2.3 + obug: 2.1.4 + semver: 7.8.5 + + '@babel/generator@8.0.0': + dependencies: + '@babel/parser': 8.0.4 + '@babel/types': 8.0.4 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@types/jsesc': 2.5.1 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@8.0.0': + dependencies: + '@babel/types': 8.0.4 + + '@babel/helper-compilation-targets@8.0.0': + dependencies: + '@babel/compat-data': 8.0.0 + '@babel/helper-validator-option': 8.0.0 + browserslist: 4.28.6 + lru-cache: 11.5.2 + semver: 7.8.5 + + '@babel/helper-create-class-features-plugin@8.0.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-annotate-as-pure': 8.0.0 + '@babel/helper-member-expression-to-functions': 8.0.0 + '@babel/helper-optimise-call-expression': 8.0.0 + '@babel/helper-replace-supers': 8.0.1(@babel/core@8.0.1) + '@babel/helper-skip-transparent-expression-wrappers': 8.0.0 + '@babel/traverse': 8.0.4 + semver: 7.8.5 + + '@babel/helper-globals@8.0.0': {} + + '@babel/helper-member-expression-to-functions@8.0.0': + dependencies: + '@babel/traverse': 8.0.4 + '@babel/types': 8.0.4 + + '@babel/helper-optimise-call-expression@8.0.0': + dependencies: + '@babel/types': 8.0.4 + + '@babel/helper-plugin-utils@8.0.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + + '@babel/helper-replace-supers@8.0.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-member-expression-to-functions': 8.0.0 + '@babel/helper-optimise-call-expression': 8.0.0 + '@babel/traverse': 8.0.4 + + '@babel/helper-skip-transparent-expression-wrappers@8.0.0': + dependencies: + '@babel/traverse': 8.0.4 + '@babel/types': 8.0.4 + + '@babel/helper-string-parser@8.0.0': {} + + '@babel/helper-validator-identifier@8.0.4': {} + + '@babel/helper-validator-option@8.0.0': {} + + '@babel/helpers@8.0.0': + dependencies: + '@babel/template': 8.0.0 + '@babel/types': 8.0.4 + + '@babel/parser@8.0.4': + dependencies: + '@babel/types': 8.0.4 + + '@babel/plugin-proposal-decorators@8.0.2(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-create-class-features-plugin': 8.0.1(@babel/core@8.0.1) + '@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.1) + '@babel/plugin-syntax-decorators': 8.0.1(@babel/core@8.0.1) + + '@babel/plugin-syntax-decorators@8.0.1(@babel/core@8.0.1)': + dependencies: + '@babel/core': 8.0.1 + '@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.1) + + '@babel/runtime-corejs3@7.29.7': + dependencies: + core-js-pure: 3.49.0 + + '@babel/runtime@7.29.7': {} + + '@babel/template@8.0.0': + dependencies: + '@babel/code-frame': 8.0.0 + '@babel/parser': 8.0.4 + '@babel/types': 8.0.4 + + '@babel/traverse@8.0.4': + dependencies: + '@babel/code-frame': 8.0.0 + '@babel/generator': 8.0.0 + '@babel/helper-globals': 8.0.0 + '@babel/parser': 8.0.4 + '@babel/template': 8.0.0 + '@babel/types': 8.0.4 + obug: 2.1.4 + + '@babel/types@8.0.4': + dependencies: + '@babel/helper-string-parser': 8.0.0 + '@babel/helper-validator-identifier': 8.0.4 + + '@borewit/text-codec@0.2.2': {} + + '@cfworker/json-schema@4.1.1': {} + + '@cloudflare/codemode@0.4.3(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(ai@6.0.202(zod@4.3.6))(zod@4.3.6)': + dependencies: + '@types/json-schema': 7.0.15 + acorn: 8.17.0 + optionalDependencies: + '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6) + ai: 6.0.202(zod@4.3.6) + zod: 4.3.6 + + '@cloudflare/kv-asset-handler@0.5.0': {} + + '@cloudflare/shell@0.4.1(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(ai@6.0.202(zod@4.3.6))(zod@4.3.6)': + dependencies: + '@cloudflare/codemode': 0.4.3(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(ai@6.0.202(zod@4.3.6))(zod@4.3.6) + isomorphic-git: 1.38.9 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - '@tanstack/ai' + - ai + - zod + + '@cloudflare/think@0.13.0(@ai-sdk/provider@3.0.14)(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(agents@0.17.4(@babel/core@8.0.1)(@babel/runtime@7.29.7)(ai@6.0.202(zod@4.3.6))(chat@4.34.0(ai@6.0.202(zod@4.3.6))(zod@4.3.6))(just-bash@3.1.0)(react@19.2.7)(rolldown@1.2.0)(vite@7.3.1(yaml@2.9.0))(zod@4.3.6))(ai@6.0.202(zod@4.3.6))(react@19.2.7)(vite@7.3.1(yaml@2.9.0))(zod@4.3.6)': + dependencies: + '@ai-sdk/anthropic': 3.0.98(zod@4.3.6) + '@ai-sdk/openai': 3.0.80(zod@4.3.6) + '@cloudflare/codemode': 0.4.3(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(ai@6.0.202(zod@4.3.6))(zod@4.3.6) + '@cloudflare/shell': 0.4.1(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(ai@6.0.202(zod@4.3.6))(zod@4.3.6) + agents: 0.17.4(@babel/core@8.0.1)(@babel/runtime@7.29.7)(ai@6.0.202(zod@4.3.6))(chat@4.34.0(ai@6.0.202(zod@4.3.6))(zod@4.3.6))(just-bash@3.1.0)(react@19.2.7)(rolldown@1.2.0)(vite@7.3.1(yaml@2.9.0))(zod@4.3.6) + ai: 6.0.202(zod@4.3.6) + aywson: 0.0.16 + chat: 4.34.0(ai@6.0.202(zod@4.3.6))(zod@4.3.6) + create-think: 0.1.1 + just-bash: 3.1.0 + smol-toml: 1.7.0 + workers-ai-provider: 3.3.1(@ai-sdk/anthropic@3.0.98(zod@4.3.6))(@ai-sdk/openai@3.0.80(zod@4.3.6))(@ai-sdk/provider@3.0.14)(ai@6.0.202(zod@4.3.6)) + yargs: 18.0.0 + zod: 4.3.6 + optionalDependencies: + react: 19.2.7 + vite: 7.3.1(yaml@2.9.0) + transitivePeerDependencies: + - '@ai-sdk/google' + - '@ai-sdk/provider' + - '@modelcontextprotocol/sdk' + - '@tanstack/ai' + - supports-color + + '@cloudflare/unenv-preset@2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260714.1)': + dependencies: + unenv: 2.0.0-rc.24 + optionalDependencies: + workerd: 1.20260714.1 + + '@cloudflare/vite-plugin@1.45.1(vite@7.3.1(yaml@2.9.0))(wrangler@4.112.0)': + dependencies: + '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260714.1) + miniflare: 4.20260714.0 + unenv: 2.0.0-rc.24 + vite: 7.3.1(yaml@2.9.0) + workerd: 1.20260714.1 + wrangler: 4.112.0 + ws: 8.21.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@cloudflare/workerd-darwin-64@1.20260714.1': + optional: true + + '@cloudflare/workerd-darwin-arm64@1.20260714.1': + optional: true + + '@cloudflare/workerd-linux-64@1.20260714.1': + optional: true + + '@cloudflare/workerd-linux-arm64@1.20260714.1': + optional: true + + '@cloudflare/workerd-windows-64@1.20260714.1': + optional: true + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@emnapi/core@1.11.2': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.11.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.27.7': + optional: true + + '@esbuild/aix-ppc64@0.28.1': + optional: true + + '@esbuild/android-arm64@0.27.7': + optional: true + + '@esbuild/android-arm64@0.28.1': + optional: true + + '@esbuild/android-arm@0.27.7': + optional: true + + '@esbuild/android-arm@0.28.1': + optional: true + + '@esbuild/android-x64@0.27.7': + optional: true + + '@esbuild/android-x64@0.28.1': + optional: true + + '@esbuild/darwin-arm64@0.27.7': + optional: true + + '@esbuild/darwin-arm64@0.28.1': + optional: true + + '@esbuild/darwin-x64@0.27.7': + optional: true + + '@esbuild/darwin-x64@0.28.1': + optional: true + + '@esbuild/freebsd-arm64@0.27.7': + optional: true + + '@esbuild/freebsd-arm64@0.28.1': + optional: true + + '@esbuild/freebsd-x64@0.27.7': + optional: true + + '@esbuild/freebsd-x64@0.28.1': + optional: true + + '@esbuild/linux-arm64@0.27.7': + optional: true + + '@esbuild/linux-arm64@0.28.1': + optional: true + + '@esbuild/linux-arm@0.27.7': + optional: true + + '@esbuild/linux-arm@0.28.1': + optional: true + + '@esbuild/linux-ia32@0.27.7': + optional: true + + '@esbuild/linux-ia32@0.28.1': + optional: true + + '@esbuild/linux-loong64@0.27.7': + optional: true + + '@esbuild/linux-loong64@0.28.1': + optional: true + + '@esbuild/linux-mips64el@0.27.7': + optional: true + + '@esbuild/linux-mips64el@0.28.1': + optional: true + + '@esbuild/linux-ppc64@0.27.7': + optional: true + + '@esbuild/linux-ppc64@0.28.1': + optional: true + + '@esbuild/linux-riscv64@0.27.7': + optional: true + + '@esbuild/linux-riscv64@0.28.1': + optional: true + + '@esbuild/linux-s390x@0.27.7': + optional: true + + '@esbuild/linux-s390x@0.28.1': + optional: true + + '@esbuild/linux-x64@0.27.7': + optional: true + + '@esbuild/linux-x64@0.28.1': + optional: true + + '@esbuild/netbsd-arm64@0.27.7': + optional: true + + '@esbuild/netbsd-arm64@0.28.1': + optional: true + + '@esbuild/netbsd-x64@0.27.7': + optional: true + + '@esbuild/netbsd-x64@0.28.1': + optional: true + + '@esbuild/openbsd-arm64@0.27.7': + optional: true + + '@esbuild/openbsd-arm64@0.28.1': + optional: true + + '@esbuild/openbsd-x64@0.27.7': + optional: true + + '@esbuild/openbsd-x64@0.28.1': + optional: true + + '@esbuild/openharmony-arm64@0.27.7': + optional: true + + '@esbuild/openharmony-arm64@0.28.1': + optional: true + + '@esbuild/sunos-x64@0.27.7': + optional: true + + '@esbuild/sunos-x64@0.28.1': + optional: true + + '@esbuild/win32-arm64@0.27.7': + optional: true + + '@esbuild/win32-arm64@0.28.1': + optional: true + + '@esbuild/win32-ia32@0.27.7': + optional: true + + '@esbuild/win32-ia32@0.28.1': + optional: true + + '@esbuild/win32-x64@0.27.7': + optional: true + + '@esbuild/win32-x64@0.28.1': + optional: true + + '@hono/node-server@1.19.14(hono@4.12.31)': + dependencies: + hono: 4.12.31 + + '@img/colour@1.1.0': {} + + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true + + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true + + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true + + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true + + '@img/sharp-linux-ppc64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.4 + optional: true + + '@img/sharp-linux-riscv64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.2.4 + optional: true + + '@img/sharp-linux-s390x@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.4 + optional: true + + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true + + '@img/sharp-wasm32@0.34.5': + dependencies: + '@emnapi/runtime': 1.11.2 + optional: true + + '@img/sharp-win32-arm64@0.34.5': + optional: true + + '@img/sharp-win32-ia32@0.34.5': + optional: true + + '@img/sharp-win32-x64@0.34.5': + optional: true + + '@jitl/quickjs-ffi-types@0.32.0': {} + + '@jitl/quickjs-wasmfile-debug-asyncify@0.32.0': + dependencies: + '@jitl/quickjs-ffi-types': 0.32.0 + + '@jitl/quickjs-wasmfile-debug-sync@0.32.0': + dependencies: + '@jitl/quickjs-ffi-types': 0.32.0 + + '@jitl/quickjs-wasmfile-release-asyncify@0.32.0': + dependencies: + '@jitl/quickjs-ffi-types': 0.32.0 + + '@jitl/quickjs-wasmfile-release-sync@0.32.0': + dependencies: + '@jitl/quickjs-ffi-types': 0.32.0 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@mixmark-io/domino@2.2.0': {} + + '@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6)': + dependencies: + '@hono/node-server': 1.19.14(hono@4.12.31) + 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.6.0(express@5.2.1) + hono: 4.12.31 + jose: 6.2.3 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 4.3.6 + zod-to-json-schema: 3.25.2(zod@4.3.6) + optionalDependencies: + '@cfworker/json-schema': 4.1.1 + transitivePeerDependencies: + - supports-color + + '@mongodb-js/zstd@7.0.0': + dependencies: + node-addon-api: 8.9.0 + prebuild-install: 7.1.3 + optional: true + + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@nodable/entities@3.0.0': {} + + '@opentelemetry/api@1.9.1': {} + + '@oxc-project/types@0.140.0': {} + + '@poppinss/colors@4.1.6': + dependencies: + kleur: 4.1.5 + + '@poppinss/dumper@0.6.5': + dependencies: + '@poppinss/colors': 4.1.6 + '@sindresorhus/is': 7.2.0 + supports-color: 10.2.2 + + '@poppinss/exception@1.2.3': {} + + '@rolldown/binding-android-arm64@1.2.0': + optional: true + + '@rolldown/binding-darwin-arm64@1.2.0': + optional: true + + '@rolldown/binding-darwin-x64@1.2.0': + optional: true + + '@rolldown/binding-freebsd-x64@1.2.0': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.2.0': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.2.0': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.2.0': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.2.0': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.2.0': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.2.0': + optional: true + + '@rolldown/binding-linux-x64-musl@1.2.0': + optional: true + + '@rolldown/binding-openharmony-arm64@1.2.0': + optional: true + + '@rolldown/binding-wasm32-wasi@1.2.0': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.2.0': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.2.0': + optional: true + + '@rolldown/plugin-babel@0.2.3(@babel/core@8.0.1)(@babel/runtime@7.29.7)(rolldown@1.2.0)(vite@7.3.1(yaml@2.9.0))': + dependencies: + '@babel/core': 8.0.1 + picomatch: 4.0.5 + rolldown: 1.2.0 + optionalDependencies: + '@babel/runtime': 7.29.7 + vite: 7.3.1(yaml@2.9.0) + + '@rolldown/pluginutils@1.0.1': {} + + '@rollup/rollup-android-arm-eabi@4.62.2': + optional: true + + '@rollup/rollup-android-arm64@4.62.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.62.2': + optional: true + + '@rollup/rollup-darwin-x64@4.62.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.62.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.62.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.62.2': + optional: true + + '@rollup/rollup-openbsd-x64@4.62.2': + optional: true + + '@rollup/rollup-openharmony-arm64@4.62.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.62.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.62.2': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.62.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.62.2': + optional: true + + '@sindresorhus/is@7.2.0': {} + + '@speed-highlight/core@1.2.17': {} + + '@standard-schema/spec@1.1.0': {} + + '@tokenizer/inflate@0.4.1': + dependencies: + debug: 4.4.3 + token-types: 6.1.2 + transitivePeerDependencies: + - supports-color + + '@tokenizer/token@0.3.0': {} + + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/debug@4.1.13': + dependencies: + '@types/ms': 2.1.0 + + '@types/estree@1.0.9': {} + + '@types/gensync@1.0.5': {} + + '@types/jsesc@2.5.1': {} + + '@types/json-schema@7.0.15': {} + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/ms@2.1.0': {} + + '@types/unist@3.0.3': {} + + '@vercel/oidc@3.2.0': {} + + '@workflow/serde@4.1.0-beta.2': {} + + 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 + + acorn@8.17.0: {} + + agents@0.17.4(@babel/core@8.0.1)(@babel/runtime@7.29.7)(ai@6.0.202(zod@4.3.6))(chat@4.34.0(ai@6.0.202(zod@4.3.6))(zod@4.3.6))(just-bash@3.1.0)(react@19.2.7)(rolldown@1.2.0)(vite@7.3.1(yaml@2.9.0))(zod@4.3.6): + dependencies: + '@babel/plugin-proposal-decorators': 8.0.2(@babel/core@8.0.1) + '@cfworker/json-schema': 4.1.1 + '@cloudflare/codemode': 0.4.3(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(ai@6.0.202(zod@4.3.6))(zod@4.3.6) + '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6) + '@rolldown/plugin-babel': 0.2.3(@babel/core@8.0.1)(@babel/runtime@7.29.7)(rolldown@1.2.0)(vite@7.3.1(yaml@2.9.0)) + cron-schedule: 6.0.0 + esbuild: 0.28.1 + mimetext: 3.0.28 + nanoid: 5.1.16 + partyserver: 0.5.8 + partysocket: 1.3.0(react@19.2.7) + react: 19.2.7 + yaml: 2.9.0 + yargs: 18.0.0 + zod: 4.3.6 + optionalDependencies: + ai: 6.0.202(zod@4.3.6) + chat: 4.34.0(ai@6.0.202(zod@4.3.6))(zod@4.3.6) + just-bash: 3.1.0 + vite: 7.3.1(yaml@2.9.0) + transitivePeerDependencies: + - '@babel/core' + - '@babel/plugin-transform-runtime' + - '@babel/runtime' + - '@cloudflare/workers-types' + - rolldown + - supports-color + + ai@6.0.202(zod@4.3.6): + dependencies: + '@ai-sdk/gateway': 3.0.128(zod@4.3.6) + '@ai-sdk/provider': 3.0.10 + '@ai-sdk/provider-utils': 4.0.28(zod@4.3.6) + '@opentelemetry/api': 1.9.1 + zod: 4.3.6 + + 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.4 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@6.2.2: {} + + ansi-styles@6.2.3: {} + + anynum@1.0.1: {} + + async-lock@1.4.1: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + aywson@0.0.16: + dependencies: + chalk: 5.6.2 + jsonc-parser: 3.3.1 + + bail@2.0.2: {} + + balanced-match@4.0.4: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.10.43: {} + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + optional: true + + blake3-wasm@2.1.5: {} + + body-parser@2.3.0: + dependencies: + bytes: 3.1.2 + content-type: 2.0.0 + debug: 4.4.3 + http-errors: 2.0.1 + iconv-lite: 0.7.3 + on-finished: 2.4.1 + qs: 6.15.3 + raw-body: 3.0.2 + type-is: 2.1.0 + transitivePeerDependencies: + - supports-color + + brace-expansion@5.0.7: + dependencies: + balanced-match: 4.0.4 + + browserslist@4.28.6: + dependencies: + baseline-browser-mapping: 2.10.43 + caniuse-lite: 1.0.30001806 + electron-to-chromium: 1.5.393 + node-releases: 2.0.51 + update-browserslist-db: 1.2.3(browserslist@4.28.6) + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + optional: true + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bytes@3.1.2: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.9: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + caniuse-lite@1.0.30001806: {} + + ccount@2.0.1: {} + + chalk@5.6.2: {} + + character-entities@2.0.2: {} + + chat@4.34.0(ai@6.0.202(zod@4.3.6))(zod@4.3.6): + dependencies: + '@workflow/serde': 4.1.0-beta.2 + mdast-util-to-string: 4.0.0 + remark-gfm: 4.0.1 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + remend: 1.3.0 + unified: 11.0.5 + optionalDependencies: + ai: 6.0.202(zod@4.3.6) + zod: 4.3.6 + transitivePeerDependencies: + - supports-color + + chownr@1.1.4: + optional: true + + clean-git-ref@2.0.1: {} + + cliui@9.0.1: + dependencies: + string-width: 7.2.0 + strip-ansi: 7.2.0 + wrap-ansi: 9.0.2 + + commander@6.2.1: {} + + content-disposition@1.1.0: {} + + content-type@1.0.5: {} + + content-type@2.0.0: {} + + convert-source-map@2.0.0: {} + + cookie-signature@1.2.2: {} + + cookie@0.7.2: {} + + cookie@1.1.1: {} + + core-js-pure@3.49.0: {} + + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + crc-32@1.2.2: {} + + create-think@0.1.1: {} + + cron-schedule@6.0.0: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + dc-browser@1.0.4: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decode-named-character-reference@1.3.0: + dependencies: + character-entities: 2.0.2 + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + deep-extend@0.6.0: + optional: true + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + depd@2.0.0: {} + + dequal@2.0.3: {} + + detect-libc@2.1.2: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + diff3@0.0.3: {} + + diff@8.0.4: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + ee-first@1.1.1: {} + + electron-to-chromium@1.5.393: {} + + emoji-regex@10.6.0: {} + + empathic@2.0.1: {} + + encodeurl@2.0.0: {} + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + optional: true + + error-stack-parser-es@1.0.5: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + esbuild@0.27.7: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 + + 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 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@5.0.0: {} + + etag@1.8.1: {} + + event-target-polyfill@0.0.4: {} + + event-target-shim@5.0.1: {} + + events@3.3.0: {} + + eventsource-parser@3.1.0: {} + + eventsource@3.0.7: + dependencies: + eventsource-parser: 3.1.0 + + expand-template@2.0.3: + optional: true + + express-rate-limit@8.6.0(express@5.2.1): + dependencies: + debug: 4.4.3 + express: 5.2.1 + ip-address: 10.2.0 + transitivePeerDependencies: + - supports-color + + express@5.2.1: + dependencies: + accepts: 2.0.0 + body-parser: 2.3.0 + 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.3 + range-parser: 1.3.0 + 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-deep-equal@3.1.3: {} + + fast-uri@3.1.4: {} + + fast-xml-builder@1.3.0: + dependencies: + path-expression-matcher: 1.6.2 + xml-naming: 0.3.0 + + fast-xml-parser@5.10.1: + dependencies: + '@nodable/entities': 3.0.0 + fast-xml-builder: 1.3.0 + is-unsafe: 2.0.0 + path-expression-matcher: 1.6.2 + strnum: 2.4.1 + xml-naming: 0.3.0 + + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + + file-type@21.3.4: + dependencies: + '@tokenizer/inflate': 0.4.1 + strtok3: 10.3.5 + token-types: 6.1.2 + uint8array-extras: 1.5.0 + transitivePeerDependencies: + - supports-color + + 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 + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + forwarded@0.2.0: {} + + fresh@2.0.0: {} + + fs-constants@1.0.0: + optional: true + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.6.0: {} + + 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 + + github-from-package@0.0.0: + optional: true + + gopd@1.2.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + 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 + + hono@4.12.31: {} + + 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 + + iconv-lite@0.7.3: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + import-meta-resolve@4.2.0: {} + + inherits@2.0.4: {} + + ini@1.3.8: + optional: true + + ini@6.0.0: {} + + ip-address@10.2.0: {} + + ipaddr.js@1.9.1: {} + + is-callable@1.2.7: {} + + is-plain-obj@4.1.0: {} + + is-promise@4.0.0: {} + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.22 + + is-unsafe@2.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isomorphic-git@1.38.9: + dependencies: + async-lock: 1.4.1 + clean-git-ref: 2.0.1 + crc-32: 1.2.2 + diff3: 0.0.3 + ignore: 5.3.2 + minimisted: 2.0.1 + pako: 1.0.11 + pify: 4.0.1 + readable-stream: 4.7.0 + sha.js: 2.4.12 + simple-get: 4.0.1 + + jose@6.2.3: {} + + js-base64@3.9.1: {} + + js-tokens@10.0.0: {} + + jsesc@3.1.0: {} + + json-schema-traverse@1.0.0: {} + + json-schema-typed@8.0.2: {} + + json-schema@0.4.0: {} + + json5@2.2.3: {} + + jsonc-parser@3.3.1: {} + + just-bash@3.1.0: + dependencies: + diff: 8.0.4 + fast-xml-parser: 5.10.1 + file-type: 21.3.4 + ini: 6.0.0 + minimatch: 10.2.5 + modern-tar: 0.7.7 + papaparse: 5.5.4 + quickjs-emscripten: 0.32.0 + re2js: 1.3.3 + seek-bzip: 2.0.0 + smol-toml: 1.7.0 + sprintf-js: 1.1.3 + sql.js: 1.14.1 + turndown: 7.2.4 + yaml: 2.9.0 + optionalDependencies: + '@mongodb-js/zstd': 7.0.0 + node-liblzma: 2.2.0 + transitivePeerDependencies: + - supports-color + + kleur@4.1.5: {} + + longest-streak@3.1.0: {} + + lru-cache@11.5.2: {} + + markdown-table@3.0.4: {} + + math-intrinsics@1.1.0: {} + + mdast-util-find-and-replace@3.0.2: + dependencies: + '@types/mdast': 4.0.4 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + mdast-util-from-markdown@2.0.3: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.2 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-autolink-literal@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.2 + micromark-util-character: 2.1.1 + + mdast-util-gfm-footnote@2.1.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + micromark-util-normalize-identifier: 2.0.1 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-strikethrough@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-table@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + markdown-table: 3.0.4 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-task-list-item@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm@3.1.0: + dependencies: + mdast-util-from-markdown: 2.0.3 + mdast-util-gfm-autolink-literal: 2.0.1 + mdast-util-gfm-footnote: 2.1.0 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-phrasing@4.1.0: + dependencies: + '@types/mdast': 4.0.4 + unist-util-is: 6.0.1 + + mdast-util-to-markdown@2.1.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 + unist-util-visit: 5.1.0 + zwitch: 2.0.4 + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + + media-typer@1.1.0: {} + + merge-descriptors@2.0.0: {} + + micromark-core-commonmark@2.0.3: + dependencies: + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-autolink-literal@2.1.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-footnote@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-strikethrough@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-table@2.1.1: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-tagfilter@2.0.0: + dependencies: + micromark-util-types: 2.0.2 + + micromark-extension-gfm-task-list-item@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm@3.0.0: + dependencies: + micromark-extension-gfm-autolink-literal: 2.1.0 + micromark-extension-gfm-footnote: 2.1.0 + micromark-extension-gfm-strikethrough: 2.1.0 + micromark-extension-gfm-table: 2.1.1 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.1.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-destination@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-label@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-space@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.2 + + micromark-factory-title@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-whitespace@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-chunked@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-classify-character@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-combine-extensions@2.0.1: + dependencies: + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-decode-numeric-character-reference@2.0.2: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-decode-string@2.0.1: + dependencies: + decode-named-character-reference: 1.3.0 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 + + micromark-util-encode@2.0.1: {} + + micromark-util-html-tag-name@2.0.1: {} + + micromark-util-normalize-identifier@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-resolve-all@2.0.1: + dependencies: + micromark-util-types: 2.0.2 + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-subtokenize@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + + micromark@4.0.2: + dependencies: + '@types/debug': 4.1.13 + debug: 4.4.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + transitivePeerDependencies: + - supports-color + + 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 + + mimetext@3.0.28: + dependencies: + '@babel/runtime': 7.29.7 + '@babel/runtime-corejs3': 7.29.7 + js-base64: 3.9.1 + mime-types: 2.1.35 + + mimic-response@3.1.0: {} + + miniflare@4.20260714.0: + dependencies: + '@cspotcode/source-map-support': 0.8.1 + sharp: 0.34.5 + undici: 7.28.0 + workerd: 1.20260714.1 + ws: 8.21.0 + youch: 4.1.0-beta.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.7 + + minimist@1.2.8: {} + + minimisted@2.0.1: + dependencies: + minimist: 1.2.8 + + mkdirp-classic@0.5.3: + optional: true + + modern-tar@0.7.7: {} + + ms@2.1.3: {} + + nanoid@3.3.16: {} + + nanoid@5.1.16: {} + + napi-build-utils@2.0.0: + optional: true + + negotiator@1.0.0: {} + + node-abi@3.94.0: + dependencies: + semver: 7.8.5 + optional: true + + node-addon-api@8.9.0: + optional: true + + node-gyp-build@4.8.4: + optional: true + + node-liblzma@2.2.0: + dependencies: + node-addon-api: 8.9.0 + node-gyp-build: 4.8.4 + optional: true + + node-releases@2.0.51: {} + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + obug@2.1.4: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + pako@1.0.11: {} + + papaparse@5.5.4: {} + + parseurl@1.3.3: {} + + partyserver@0.5.8: + dependencies: + nanoid: 5.1.16 + + partysocket@1.3.0(react@19.2.7): + dependencies: + event-target-polyfill: 0.0.4 + optionalDependencies: + react: 19.2.7 + + path-expression-matcher@1.6.2: {} + + path-key@3.1.1: {} + + path-to-regexp@6.3.0: {} + + path-to-regexp@8.4.2: {} + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@4.0.5: {} + + pify@4.0.1: {} + + pkce-challenge@5.0.1: {} + + possible-typed-array-names@1.1.0: {} + + postcss@8.5.20: + dependencies: + nanoid: 3.3.16 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prebuild-install@7.1.3: + dependencies: + detect-libc: 2.1.2 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 2.0.0 + node-abi: 3.94.0 + pump: 3.0.4 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.5 + tunnel-agent: 0.6.0 + optional: true + + process@0.11.10: {} + + 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 + optional: true + + qs@6.15.3: + dependencies: + es-define-property: 1.0.1 + side-channel: 1.1.1 + + quickjs-emscripten-core@0.32.0: + dependencies: + '@jitl/quickjs-ffi-types': 0.32.0 + + quickjs-emscripten@0.32.0: + dependencies: + '@jitl/quickjs-wasmfile-debug-asyncify': 0.32.0 + '@jitl/quickjs-wasmfile-debug-sync': 0.32.0 + '@jitl/quickjs-wasmfile-release-asyncify': 0.32.0 + '@jitl/quickjs-wasmfile-release-sync': 0.32.0 + quickjs-emscripten-core: 0.32.0 + + range-parser@1.3.0: {} + + raw-body@3.0.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.7.3 + unpipe: 1.0.0 + + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + optional: true + + re2js@1.3.3: {} + + react@19.2.7: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + optional: true + + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + remark-gfm@4.0.1: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-gfm: 3.1.0 + micromark-extension-gfm: 3.0.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-parse@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.3 + micromark-util-types: 2.0.2 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-stringify@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-to-markdown: 2.1.2 + unified: 11.0.5 + + remend@1.3.0: {} + + require-from-string@2.0.2: {} + + rolldown@1.2.0: + dependencies: + '@oxc-project/types': 0.140.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.2.0 + '@rolldown/binding-darwin-arm64': 1.2.0 + '@rolldown/binding-darwin-x64': 1.2.0 + '@rolldown/binding-freebsd-x64': 1.2.0 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.0 + '@rolldown/binding-linux-arm64-gnu': 1.2.0 + '@rolldown/binding-linux-arm64-musl': 1.2.0 + '@rolldown/binding-linux-ppc64-gnu': 1.2.0 + '@rolldown/binding-linux-s390x-gnu': 1.2.0 + '@rolldown/binding-linux-x64-gnu': 1.2.0 + '@rolldown/binding-linux-x64-musl': 1.2.0 + '@rolldown/binding-openharmony-arm64': 1.2.0 + '@rolldown/binding-wasm32-wasi': 1.2.0 + '@rolldown/binding-win32-arm64-msvc': 1.2.0 + '@rolldown/binding-win32-x64-msvc': 1.2.0 + + rollup@4.62.2: + dependencies: + '@types/estree': 1.0.9 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.62.2 + '@rollup/rollup-android-arm64': 4.62.2 + '@rollup/rollup-darwin-arm64': 4.62.2 + '@rollup/rollup-darwin-x64': 4.62.2 + '@rollup/rollup-freebsd-arm64': 4.62.2 + '@rollup/rollup-freebsd-x64': 4.62.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.2 + '@rollup/rollup-linux-arm-musleabihf': 4.62.2 + '@rollup/rollup-linux-arm64-gnu': 4.62.2 + '@rollup/rollup-linux-arm64-musl': 4.62.2 + '@rollup/rollup-linux-loong64-gnu': 4.62.2 + '@rollup/rollup-linux-loong64-musl': 4.62.2 + '@rollup/rollup-linux-ppc64-gnu': 4.62.2 + '@rollup/rollup-linux-ppc64-musl': 4.62.2 + '@rollup/rollup-linux-riscv64-gnu': 4.62.2 + '@rollup/rollup-linux-riscv64-musl': 4.62.2 + '@rollup/rollup-linux-s390x-gnu': 4.62.2 + '@rollup/rollup-linux-x64-gnu': 4.62.2 + '@rollup/rollup-linux-x64-musl': 4.62.2 + '@rollup/rollup-openbsd-x64': 4.62.2 + '@rollup/rollup-openharmony-arm64': 4.62.2 + '@rollup/rollup-win32-arm64-msvc': 4.62.2 + '@rollup/rollup-win32-ia32-msvc': 4.62.2 + '@rollup/rollup-win32-x64-gnu': 4.62.2 + '@rollup/rollup-win32-x64-msvc': 4.62.2 + fsevents: 2.3.3 + + 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: {} + + safer-buffer@2.1.2: {} + + seek-bzip@2.0.0: + dependencies: + commander: 6.2.1 + + semver@7.8.5: {} + + 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.3.0 + 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-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + setprototypeof@1.2.0: {} + + sha.js@2.4.12: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + + sharp@0.34.5: + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.8.5 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.5 + '@img/sharp-darwin-x64': 0.34.5 + '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-x64': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.2.4 + '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + '@img/sharp-linux-arm': 0.34.5 + '@img/sharp-linux-arm64': 0.34.5 + '@img/sharp-linux-ppc64': 0.34.5 + '@img/sharp-linux-riscv64': 0.34.5 + '@img/sharp-linux-s390x': 0.34.5 + '@img/sharp-linux-x64': 0.34.5 + '@img/sharp-linuxmusl-arm64': 0.34.5 + '@img/sharp-linuxmusl-x64': 0.34.5 + '@img/sharp-wasm32': 0.34.5 + '@img/sharp-win32-arm64': 0.34.5 + '@img/sharp-win32-ia32': 0.34.5 + '@img/sharp-win32-x64': 0.34.5 + + 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 + + simple-concat@1.0.1: {} + + simple-get@4.0.1: + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + + smol-toml@1.7.0: {} + + source-map-js@1.2.1: {} + + sprintf-js@1.1.3: {} + + sql.js@1.14.1: {} + + statuses@2.0.2: {} + + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.6.0 + strip-ansi: 7.2.0 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + strip-json-comments@2.0.1: + optional: true + + strnum@2.4.1: + dependencies: + anynum: 1.0.1 + + strtok3@10.3.5: + dependencies: + '@tokenizer/token': 0.3.0 + + supports-color@10.2.2: {} + + tar-fs@2.1.5: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.4 + tar-stream: 2.2.0 + optional: true + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + optional: true + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + + to-buffer@1.2.2: + dependencies: + isarray: 2.0.5 + safe-buffer: 5.2.1 + typed-array-buffer: 1.0.3 + + toidentifier@1.0.1: {} + + token-types@6.1.2: + dependencies: + '@borewit/text-codec': 0.2.2 + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + + trough@2.2.0: {} + + tslib@2.8.1: + optional: true + + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + optional: true + + turndown@7.2.4: + dependencies: + '@mixmark-io/domino': 2.2.0 + + type-is@2.1.0: + dependencies: + content-type: 2.0.0 + media-typer: 1.1.0 + mime-types: 3.0.2 + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + uint8array-extras@1.5.0: {} + + undici@7.28.0: {} + + unenv@2.0.0-rc.24: + dependencies: + pathe: 2.0.3 + + unified@11.0.5: + dependencies: + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 + + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + unpipe@1.0.0: {} + + update-browserslist-db@1.2.3(browserslist@4.28.6): + dependencies: + browserslist: 4.28.6 + escalade: 3.2.0 + picocolors: 1.1.1 + + util-deprecate@1.0.2: + optional: true + + vary@1.1.2: {} + + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + + vite@7.3.1(yaml@2.9.0): + dependencies: + esbuild: 0.27.7 + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + postcss: 8.5.20 + rollup: 4.62.2 + tinyglobby: 0.2.17 + optionalDependencies: + fsevents: 2.3.3 + yaml: 2.9.0 + + which-typed-array@1.1.22: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + workerd@1.20260714.1: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20260714.1 + '@cloudflare/workerd-darwin-arm64': 1.20260714.1 + '@cloudflare/workerd-linux-64': 1.20260714.1 + '@cloudflare/workerd-linux-arm64': 1.20260714.1 + '@cloudflare/workerd-windows-64': 1.20260714.1 + + workers-ai-provider@3.3.1(@ai-sdk/anthropic@3.0.98(zod@4.3.6))(@ai-sdk/openai@3.0.80(zod@4.3.6))(@ai-sdk/provider@3.0.14)(ai@6.0.202(zod@4.3.6)): + dependencies: + '@ai-sdk/provider': 3.0.14 + ai: 6.0.202(zod@4.3.6) + optionalDependencies: + '@ai-sdk/anthropic': 3.0.98(zod@4.3.6) + '@ai-sdk/openai': 3.0.80(zod@4.3.6) + + wrangler@4.112.0: + dependencies: + '@cloudflare/kv-asset-handler': 0.5.0 + '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260714.1) + blake3-wasm: 2.1.5 + esbuild: 0.28.1 + miniflare: 4.20260714.0 + path-to-regexp: 6.3.0 + unenv: 2.0.0-rc.24 + workerd: 1.20260714.1 + optionalDependencies: + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.2.0 + + wrappy@1.0.2: {} + + ws@8.21.0: {} + + xml-naming@0.3.0: {} + + y18n@5.0.8: {} + + yaml@2.9.0: {} + + yargs-parser@22.0.0: {} + + yargs@18.0.0: + dependencies: + cliui: 9.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + string-width: 7.2.0 + y18n: 5.0.8 + yargs-parser: 22.0.0 + + youch-core@0.3.3: + dependencies: + '@poppinss/exception': 1.2.3 + error-stack-parser-es: 1.0.5 + + youch@4.1.0-beta.10: + dependencies: + '@poppinss/colors': 4.1.6 + '@poppinss/dumper': 0.6.5 + '@speed-highlight/core': 1.2.17 + cookie: 1.1.1 + youch-core: 0.3.3 + + zod-to-json-schema@3.25.2(zod@4.3.6): + dependencies: + zod: 4.3.6 + + zod@4.3.6: {} + + zwitch@2.0.4: {} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/scenario.test.ts b/e2e/scenarios/cloudflare-think-instrumentation/scenario.test.ts new file mode 100644 index 000000000..19d3a1101 --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/scenario.test.ts @@ -0,0 +1,68 @@ +import { describe } from "vitest"; +import { + prepareScenarioDir, + readInstalledPackageVersion, + resolveScenarioDir, +} from "../../helpers/scenario-harness"; +import { defineCloudflareThinkAssertions } from "./assertions"; + +const originalScenarioDir = resolveScenarioDir(import.meta.url); +const scenarioDir = await prepareScenarioDir({ + scenarioDir: originalScenarioDir, +}); +const TIMEOUT_MS = 300_000; +const variants = await Promise.all( + [ + { + dependencyName: "cloudflare-think-v0", + label: "0.13 pinned", + variantKey: "cloudflare-think-v0", + }, + { + dependencyName: "cloudflare-think-v0-latest", + label: "0.13 latest", + variantKey: "cloudflare-think-v0-latest", + }, + ].map(async (variant) => ({ + ...variant, + version: await readInstalledPackageVersion( + scenarioDir, + variant.dependencyName, + ), + })), +); + +const describeVariants = + process.env.BRAINTRUST_E2E_CASSETTE_MODE === "record" || + process.env.BRAINTRUST_E2E_CASSETTE_MODE === "record-missing" + ? describe.sequential + : describe.concurrent; + +describeVariants("Cloudflare Think variants", () => { + for (const variant of variants) { + describe.sequential(`${variant.label} (${variant.version})`, () => { + for (const mode of ["manual", "auto"] as const) { + defineCloudflareThinkAssertions({ + name: `${mode} Workers/Vite instrumentation`, + runScenario: async ({ runScenarioDir }) => { + await runScenarioDir({ + env: { + CLOUDFLARE_THINK_INSTRUMENTATION: mode, + CLOUDFLARE_THINK_PACKAGE_NAME: variant.dependencyName, + }, + runContext: { + originalScenarioDir, + variantKey: `${variant.variantKey}-${mode}`, + }, + scenarioDir, + timeoutMs: TIMEOUT_MS, + }); + }, + snapshotName: `${variant.variantKey}-${mode}`, + testFileUrl: import.meta.url, + timeoutMs: TIMEOUT_MS, + }); + } + }); + } +}); diff --git a/e2e/scenarios/cloudflare-think-instrumentation/scenario.ts b/e2e/scenarios/cloudflare-think-instrumentation/scenario.ts new file mode 100644 index 000000000..7e35d0874 --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/scenario.ts @@ -0,0 +1,97 @@ +import { spawn } from "node:child_process"; +import { writeFile } from "node:fs/promises"; +import { createRequire } from "node:module"; +import path from "node:path"; + +const require = createRequire(import.meta.url); +const viteBin = path.join( + path.dirname(require.resolve("vite/package.json")), + "bin/vite.js", +); +const port = 9400 + Math.floor(Math.random() * 400); +const origin = `http://127.0.0.1:${port}`; +await writeFile( + ".dev.vars", + [ + `BRAINTRUST_APP_URL=${requiredEnv("BRAINTRUST_APP_URL")}`, + `BRAINTRUST_API_URL=${requiredEnv("BRAINTRUST_API_URL")}`, + `BRAINTRUST_API_KEY=${requiredEnv("BRAINTRUST_API_KEY")}`, + `BRAINTRUST_E2E_PROJECT_NAME=${ + process.env.BRAINTRUST_E2E_PROJECT_NAME || + "cloudflare-think-instrumentation" + }`, + `BRAINTRUST_E2E_RUN_ID=${requiredEnv("BRAINTRUST_E2E_RUN_ID")}`, + `OPENAI_API_KEY=${requiredEnv("OPENAI_API_KEY")}`, + `OPENAI_BASE_URL=${requiredEnv("OPENAI_BASE_URL")}`, + ].join("\n"), +); +const child = spawn( + process.execPath, + [ + viteBin, + "--host", + "127.0.0.1", + "--port", + String(port), + "--strictPort", + "--force", + ], + { + env: process.env, + stdio: ["ignore", "pipe", "pipe"], + }, +); +let output = ""; +child.stdout.on("data", (chunk) => (output += chunk.toString())); +child.stderr.on("data", (chunk) => (output += chunk.toString())); + +try { + await waitUntilReady(`${origin}/health`); + const url = new URL(origin); + url.searchParams.set("agent", `agent-${process.env.BRAINTRUST_E2E_RUN_ID}`); + url.searchParams.set("braintrustAppUrl", requiredEnv("BRAINTRUST_APP_URL")); + url.searchParams.set("braintrustApiUrl", requiredEnv("BRAINTRUST_API_URL")); + const response = await fetch(url); + const body = await response.text(); + if (!response.ok) { + throw new Error( + `Think worker returned ${response.status}: ${body}\n${output}`, + ); + } + const result = JSON.parse(body) as { status?: string }; + if (result.status !== "completed") { + throw new Error(`Unexpected Think result: ${body}`); + } +} finally { + child.kill("SIGTERM"); + if (child.exitCode === null) { + await new Promise((resolve) => child.once("close", () => resolve())); + } +} + +async function waitUntilReady(url: string): Promise { + const deadline = Date.now() + 90_000; + while (Date.now() < deadline) { + if (child.exitCode !== null) { + throw new Error(`Vite exited before becoming ready:\n${output}`); + } + try { + const response = await fetch(url); + if (response.ok) { + return; + } + } catch { + // The dev server is still starting. + } + await new Promise((resolve) => setTimeout(resolve, 250)); + } + throw new Error(`Timed out waiting for Vite:\n${output}`); +} + +function requiredEnv(name: string): string { + const value = process.env[name]; + if (!value) { + throw new Error(`Missing ${name}`); + } + return value; +} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/src/worker.ts b/e2e/scenarios/cloudflare-think-instrumentation/src/worker.ts new file mode 100644 index 000000000..155edbf3f --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/src/worker.ts @@ -0,0 +1,89 @@ +import * as cloudflareThink from "@cloudflare/think"; +import { createOpenAI } from "@ai-sdk/openai"; +import { flush, initLogger, wrapCloudflareThink } from "braintrust"; +import { tool } from "ai"; +import { z } from "zod"; + +const OPENAI_MODEL = "gpt-5-nano"; + +type Env = { + THINK_AGENT: DurableObjectNamespace; +}; + +const think = + process.env.CLOUDFLARE_THINK_INSTRUMENTATION === "manual" + ? wrapCloudflareThink(cloudflareThink) + : cloudflareThink; + +export class TestThink extends think.Think { + async runE2ETurn() { + if (!this.session) { + await this.onStart(); + } + return this.runTurn({ + input: "What is the weather in Vienna?", + mode: "wait", + }); + } + + getModel() { + return createOpenAI({ + apiKey: process.env.OPENAI_API_KEY, + baseURL: process.env.OPENAI_BASE_URL, + }).chat(OPENAI_MODEL); + } + + getSystemPrompt() { + return [ + "You are a deterministic weather-test agent.", + "You must call lookup_weather exactly once with Vienna before answering.", + 'After the tool result, reply with exactly: "Vienna is sunny and 21°C."', + ].join(" "); + } + + getTools() { + return { + lookup_weather: tool({ + description: "Get deterministic weather for a city.", + inputSchema: z.object({ city: z.string() }), + execute: async ({ city }) => ({ + city, + condition: "sunny", + degreesC: 21, + }), + }), + }; + } +} + +export default { + async fetch(request: Request, env: Env): Promise { + const url = new URL(request.url); + if (url.pathname === "/health") { + return new Response("ok"); + } + + configureBraintrust(url); + const agent = env.THINK_AGENT.getByName( + url.searchParams.get("agent") ?? "default", + ); + const result = await agent.runE2ETurn(); + await flush(); + return Response.json(result); + }, +}; + +function configureBraintrust(url: URL): void { + const appUrl = url.searchParams.get("braintrustAppUrl"); + const apiUrl = url.searchParams.get("braintrustApiUrl"); + if (!appUrl || !apiUrl) { + throw new Error("Missing Braintrust E2E server URLs"); + } + initLogger({ + apiKey: process.env.BRAINTRUST_API_KEY, + appUrl, + projectName: + process.env.BRAINTRUST_E2E_PROJECT_NAME || + "cloudflare-think-instrumentation", + }); +} diff --git a/e2e/scenarios/cloudflare-think-instrumentation/src/wrapped-ai.ts b/e2e/scenarios/cloudflare-think-instrumentation/src/wrapped-ai.ts new file mode 100644 index 000000000..9f72716f0 --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/src/wrapped-ai.ts @@ -0,0 +1,8 @@ +import * as ai from "ai-unwrapped"; +import { wrapAISDK } from "braintrust"; + +export * from "ai-unwrapped"; + +const wrapped = wrapAISDK(ai); + +export const streamText = wrapped.streamText; diff --git a/e2e/scenarios/cloudflare-think-instrumentation/vite.config.ts b/e2e/scenarios/cloudflare-think-instrumentation/vite.config.ts new file mode 100644 index 000000000..3bb43d951 --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/vite.config.ts @@ -0,0 +1,31 @@ +import { cloudflare } from "@cloudflare/vite-plugin"; +import { defineConfig } from "vite"; +import { braintrustVitePlugin } from "braintrust/vite"; + +const manual = process.env.CLOUDFLARE_THINK_INSTRUMENTATION === "manual"; +const thinkPackageName = + process.env.CLOUDFLARE_THINK_PACKAGE_NAME ?? "cloudflare-think-v0-latest"; + +export default defineConfig({ + define: { + "process.env.CLOUDFLARE_THINK_INSTRUMENTATION": JSON.stringify( + manual ? "manual" : "auto", + ), + }, + plugins: [ + ...(manual + ? [] + : [braintrustVitePlugin({ useDiagnosticChannelCompatShim: true })]), + cloudflare(), + ], + resolve: { + alias: { + "@cloudflare/think": thinkPackageName, + ...(manual + ? { + ai: new URL("./src/wrapped-ai.ts", import.meta.url).pathname, + } + : {}), + }, + }, +}); diff --git a/e2e/scenarios/cloudflare-think-instrumentation/wrangler.jsonc b/e2e/scenarios/cloudflare-think-instrumentation/wrangler.jsonc new file mode 100644 index 000000000..9f774694f --- /dev/null +++ b/e2e/scenarios/cloudflare-think-instrumentation/wrangler.jsonc @@ -0,0 +1,21 @@ +{ + "$schema": "node_modules/wrangler/config-schema.json", + "name": "braintrust-cloudflare-think-e2e", + "main": "src/worker.ts", + "compatibility_date": "2026-07-20", + "compatibility_flags": ["nodejs_compat"], + "durable_objects": { + "bindings": [ + { + "name": "THINK_AGENT", + "class_name": "TestThink", + }, + ], + }, + "migrations": [ + { + "tag": "v1", + "new_sqlite_classes": ["TestThink"], + }, + ], +} diff --git a/js/src/auto-instrumentations/bundler/plugin.ts b/js/src/auto-instrumentations/bundler/plugin.ts index dda1b7490..4815709be 100644 --- a/js/src/auto-instrumentations/bundler/plugin.ts +++ b/js/src/auto-instrumentations/bundler/plugin.ts @@ -1,11 +1,12 @@ import { createUnplugin } from "unplugin"; import { create, type InstrumentationConfig } from "../orchestrion-js"; -import { extname, join, sep } from "path"; +import { extname, isAbsolute, join, sep } from "path"; import { readFileSync } from "fs"; import { fileURLToPath } from "url"; import moduleDetailsFromPath from "module-details-from-path"; import { getDefaultInstrumentationConfigs } from "../configs/all"; import { applySpecialCasePatch } from "../loader/special-case-patches"; +import { getPackageName } from "../loader/get-package-version"; export interface LegacyBundlerPluginOptions { /** @@ -85,6 +86,20 @@ export const unplugin = createUnplugin( return { name: "code-transformer", enforce: "pre", + transformInclude(id: string) { + const pathWithoutQuery = id.split("?", 1)[0]; + if (!pathWithoutQuery) { + return false; + } + if (pathWithoutQuery.startsWith("file:")) { + try { + return isAbsolute(fileURLToPath(pathWithoutQuery)); + } catch { + return false; + } + } + return isAbsolute(pathWithoutQuery); + }, transform(code: string, id: string) { if (!id) { // Some modules apparently don't have an id? @@ -118,7 +133,11 @@ export const unplugin = createUnplugin( } // Use module details for accurate module information - const moduleName = moduleDetails.name; + // npm aliases retain the canonical package name in package.json even + // though their node_modules directory uses the alias. Match configs + // against that canonical name so aliased dependencies are instrumented. + const moduleName = + getPackageName(moduleDetails.basedir) ?? moduleDetails.name; // Normalize the module path for Windows compatibility (WASM transformer expects forward slashes) const normalizedModulePath = moduleDetails.path.replace(/\\/g, "/"); const moduleVersion = getModuleVersion(moduleDetails.basedir); diff --git a/js/src/auto-instrumentations/bundler/vite.ts b/js/src/auto-instrumentations/bundler/vite.ts index 6faec7cd0..e6aa278be 100644 --- a/js/src/auto-instrumentations/bundler/vite.ts +++ b/js/src/auto-instrumentations/bundler/vite.ts @@ -10,10 +10,43 @@ export function braintrustVitePlugin( options: BundlerPluginOptions = {}, ): VitePlugin | VitePlugin[] { const { useDiagnosticChannelCompatShim = false, ...pluginOptions } = options; - return unplugin.vite({ + const normalizedOptions = { ...pluginOptions, browser: useDiagnosticChannelCompatShim, - }); + }; + const transformPlugin = unplugin.vite(normalizedOptions); + const optimizeDepsPlugin: VitePlugin = { + name: "braintrust:optimize-deps", + config() { + return { + optimizeDeps: { + esbuildOptions: { + plugins: [unplugin.esbuild(normalizedOptions)], + }, + }, + }; + }, + configEnvironment(name: string) { + // The client environment inherits the root optimizer config above. + // Custom environments (including Cloudflare Workers) maintain their own + // dependency optimizer and need the transformer registered explicitly. + if (name === "client") { + return; + } + return { + optimizeDeps: { + esbuildOptions: { + plugins: [unplugin.esbuild(normalizedOptions)], + }, + }, + }; + }, + }; + + return [ + optimizeDepsPlugin, + ...(Array.isArray(transformPlugin) ? transformPlugin : [transformPlugin]), + ]; } export type VitePluginOptions = LegacyBundlerPluginOptions; diff --git a/js/src/auto-instrumentations/bundler/webpack-loader.ts b/js/src/auto-instrumentations/bundler/webpack-loader.ts index c218c21a6..5f92b274d 100644 --- a/js/src/auto-instrumentations/bundler/webpack-loader.ts +++ b/js/src/auto-instrumentations/bundler/webpack-loader.ts @@ -27,6 +27,7 @@ import { readFileSync } from "fs"; import moduleDetailsFromPath from "module-details-from-path"; import { getDefaultInstrumentationConfigs } from "../configs/all"; import { type LegacyBundlerPluginOptions } from "./plugin"; +import { getPackageName } from "../loader/get-package-version"; /** * Helper function to get module version from package.json @@ -119,7 +120,8 @@ function codeTransformerLoader( return callback(null, code, inputSourceMap); } - const moduleName = moduleDetails.name; + const moduleName = + getPackageName(moduleDetails.basedir) ?? moduleDetails.name; const moduleVersion = getModuleVersion(moduleDetails.basedir); if (!moduleVersion) { diff --git a/js/src/auto-instrumentations/configs/all.ts b/js/src/auto-instrumentations/configs/all.ts index b2d778960..c01eb99c6 100644 --- a/js/src/auto-instrumentations/configs/all.ts +++ b/js/src/auto-instrumentations/configs/all.ts @@ -8,6 +8,7 @@ import { aiSDKConfigs } from "./ai-sdk"; import { anthropicConfigs } from "./anthropic"; import { bedrockRuntimeConfigs } from "./bedrock-runtime"; import { claudeAgentSDKConfigs } from "./claude-agent-sdk"; +import { cloudflareThinkConfigs } from "./cloudflare-think"; import { cohereConfigs } from "./cohere"; import { cursorSDKConfigs } from "./cursor-sdk"; import { flueConfigs } from "./flue"; @@ -53,6 +54,10 @@ const defaultInstrumentationConfigGroups: readonly InstrumentationConfigGroup[] integrations: ["claudeAgentSDK"], configs: claudeAgentSDKConfigs, }, + { + integrations: ["cloudflareThink"], + configs: cloudflareThinkConfigs, + }, { integrations: ["cursor", "cursorSDK"], configs: cursorSDKConfigs }, { integrations: ["openAIAgents"], diff --git a/js/src/auto-instrumentations/configs/cloudflare-think.test.ts b/js/src/auto-instrumentations/configs/cloudflare-think.test.ts new file mode 100644 index 000000000..0deb66b31 --- /dev/null +++ b/js/src/auto-instrumentations/configs/cloudflare-think.test.ts @@ -0,0 +1,34 @@ +import { create } from "@apm-js-collab/code-transformer"; +import { describe, expect, it } from "vitest"; +import { cloudflareThinkConfigs } from "./cloudflare-think"; + +describe("Cloudflare Think transformation", () => { + it("instruments the supported inference loop without changing its result", () => { + const matcher = create(cloudflareThinkConfigs); + const transformer = matcher.getTransformer( + "@cloudflare/think", + "0.13.0", + "dist/think.js", + ); + + try { + expect(transformer).toBeDefined(); + const transformed = transformer!.transform( + ` +export class Think { + async _runInferenceLoop(input) { + return input; + } +} +`, + "esm", + ); + expect(transformed.code).toContain( + "orchestrion:@cloudflare/think:Think.runInferenceLoop", + ); + } finally { + transformer?.free(); + matcher.free(); + } + }); +}); diff --git a/js/src/auto-instrumentations/configs/cloudflare-think.ts b/js/src/auto-instrumentations/configs/cloudflare-think.ts new file mode 100644 index 000000000..61fb4e8ae --- /dev/null +++ b/js/src/auto-instrumentations/configs/cloudflare-think.ts @@ -0,0 +1,20 @@ +import type { InstrumentationConfig } from "../orchestrion-js"; +import { cloudflareThinkChannels } from "../../instrumentation/plugins/cloudflare-think-channels"; + +const cloudflareThinkVersionRange = ">=0.13.0 <0.14.0"; + +export const cloudflareThinkConfigs: InstrumentationConfig[] = [ + { + channelName: cloudflareThinkChannels.runInferenceLoop.channelName, + module: { + name: "@cloudflare/think", + versionRange: cloudflareThinkVersionRange, + filePath: "dist/think.js", + }, + functionQuery: { + className: "Think", + methodName: "_runInferenceLoop", + kind: "Async", + }, + }, +]; diff --git a/js/src/auto-instrumentations/index.ts b/js/src/auto-instrumentations/index.ts index ea0533ac6..959fdd679 100644 --- a/js/src/auto-instrumentations/index.ts +++ b/js/src/auto-instrumentations/index.ts @@ -34,6 +34,7 @@ export { anthropicConfigs } from "./configs/anthropic"; export { bedrockRuntimeConfigs } from "./configs/bedrock-runtime"; export { aiSDKConfigs } from "./configs/ai-sdk"; export { claudeAgentSDKConfigs } from "./configs/claude-agent-sdk"; +export { cloudflareThinkConfigs } from "./configs/cloudflare-think"; export { cursorSDKConfigs } from "./configs/cursor-sdk"; export { openAIAgentsCoreConfigs } from "./configs/openai-agents"; export { googleGenAIConfigs } from "./configs/google-genai"; diff --git a/js/src/exports.ts b/js/src/exports.ts index 36a38946a..84986550e 100644 --- a/js/src/exports.ts +++ b/js/src/exports.ts @@ -207,6 +207,7 @@ export { } from "./wrappers/mastra"; export type { MastraObservabilityExporter } from "./wrappers/mastra"; export { wrapClaudeAgentSDK } from "./wrappers/claude-agent-sdk/claude-agent-sdk"; +export { wrapCloudflareThink } from "./wrappers/cloudflare-think"; export { wrapOpenAICodexSDK } from "./wrappers/openai-codex"; export { wrapCursorSDK } from "./wrappers/cursor-sdk"; export { wrapPiCodingAgentSDK } from "./wrappers/pi-coding-agent"; diff --git a/js/src/instrumentation/braintrust-plugin.test.ts b/js/src/instrumentation/braintrust-plugin.test.ts index fdce9dc99..b84a232ac 100644 --- a/js/src/instrumentation/braintrust-plugin.test.ts +++ b/js/src/instrumentation/braintrust-plugin.test.ts @@ -5,6 +5,7 @@ import { OpenAICodexPlugin } from "./plugins/openai-codex-plugin"; import { AnthropicPlugin } from "./plugins/anthropic-plugin"; import { AISDKPlugin } from "./plugins/ai-sdk-plugin"; import { ClaudeAgentSDKPlugin } from "./plugins/claude-agent-sdk-plugin"; +import { CloudflareThinkPlugin } from "./plugins/cloudflare-think-plugin"; import { OpenAIAgentsPlugin } from "./plugins/openai-agents-plugin"; import { GoogleGenAIPlugin } from "./plugins/google-genai-plugin"; import { HuggingFacePlugin } from "./plugins/huggingface-plugin"; @@ -59,6 +60,10 @@ vi.mock("./plugins/claude-agent-sdk-plugin", () => ({ ClaudeAgentSDKPlugin: createPluginClassMock(), })); +vi.mock("./plugins/cloudflare-think-plugin", () => ({ + CloudflareThinkPlugin: createPluginClassMock(), +})); + vi.mock("./plugins/openai-agents-plugin", () => ({ OpenAIAgentsPlugin: createPluginClassMock(), })); @@ -163,6 +168,16 @@ describe("BraintrustPlugin", () => { expect(mockInstance.enable).toHaveBeenCalledTimes(1); }); + it("should create and enable Cloudflare Think plugin by default", () => { + const plugin = new BraintrustPlugin(); + plugin.enable(); + + expect(CloudflareThinkPlugin).toHaveBeenCalledTimes(1); + const mockInstance = vi.mocked(CloudflareThinkPlugin).mock.results[0] + .value; + expect(mockInstance.enable).toHaveBeenCalledTimes(1); + }); + it("should create and enable OpenAI Agents plugin by default", () => { const plugin = new BraintrustPlugin(); plugin.enable(); @@ -418,6 +433,16 @@ describe("BraintrustPlugin", () => { expect(MistralPlugin).toHaveBeenCalledTimes(1); }); + it("should not create Cloudflare Think plugin when cloudflareThink: false", () => { + const plugin = new BraintrustPlugin({ + integrations: { cloudflareThink: false }, + }); + plugin.enable(); + + expect(CloudflareThinkPlugin).not.toHaveBeenCalled(); + expect(AISDKPlugin).toHaveBeenCalledTimes(1); + }); + it("should not create OpenAI Agents plugin when openAIAgents: false", () => { const plugin = new BraintrustPlugin({ integrations: { openAIAgents: false }, @@ -602,6 +627,7 @@ describe("BraintrustPlugin", () => { anthropic: false, aisdk: false, claudeAgentSDK: false, + cloudflareThink: false, openAIAgents: false, googleGenAI: false, huggingface: false, @@ -624,6 +650,7 @@ describe("BraintrustPlugin", () => { expect(AnthropicPlugin).not.toHaveBeenCalled(); expect(AISDKPlugin).not.toHaveBeenCalled(); expect(ClaudeAgentSDKPlugin).not.toHaveBeenCalled(); + expect(CloudflareThinkPlugin).not.toHaveBeenCalled(); expect(OpenAIAgentsPlugin).not.toHaveBeenCalled(); expect(GoogleGenAIPlugin).not.toHaveBeenCalled(); expect(HuggingFacePlugin).not.toHaveBeenCalled(); diff --git a/js/src/instrumentation/braintrust-plugin.ts b/js/src/instrumentation/braintrust-plugin.ts index d5435f2b0..ef57315b6 100644 --- a/js/src/instrumentation/braintrust-plugin.ts +++ b/js/src/instrumentation/braintrust-plugin.ts @@ -4,6 +4,7 @@ import { OpenAICodexPlugin } from "./plugins/openai-codex-plugin"; import { AnthropicPlugin } from "./plugins/anthropic-plugin"; import { AISDKPlugin } from "./plugins/ai-sdk-plugin"; import { ClaudeAgentSDKPlugin } from "./plugins/claude-agent-sdk-plugin"; +import { CloudflareThinkPlugin } from "./plugins/cloudflare-think-plugin"; import { CursorSDKPlugin } from "./plugins/cursor-sdk-plugin"; import { OpenAIAgentsPlugin } from "./plugins/openai-agents-plugin"; import { GoogleGenAIPlugin } from "./plugins/google-genai-plugin"; @@ -52,6 +53,7 @@ export class BraintrustPlugin extends BasePlugin { private anthropicPlugin: AnthropicPlugin | null = null; private aiSDKPlugin: AISDKPlugin | null = null; private claudeAgentSDKPlugin: ClaudeAgentSDKPlugin | null = null; + private cloudflareThinkPlugin: CloudflareThinkPlugin | null = null; private cursorSDKPlugin: CursorSDKPlugin | null = null; private openAIAgentsPlugin: OpenAIAgentsPlugin | null = null; private googleGenAIPlugin: GoogleGenAIPlugin | null = null; @@ -109,6 +111,11 @@ export class BraintrustPlugin extends BasePlugin { this.claudeAgentSDKPlugin.enable(); } + if (integrations.cloudflareThink !== false) { + this.cloudflareThinkPlugin = new CloudflareThinkPlugin(); + this.cloudflareThinkPlugin.enable(); + } + if (integrations.cursorSDK !== false && integrations.cursor !== false) { this.cursorSDKPlugin = new CursorSDKPlugin(); this.cursorSDKPlugin.enable(); @@ -242,6 +249,11 @@ export class BraintrustPlugin extends BasePlugin { this.claudeAgentSDKPlugin = null; } + if (this.cloudflareThinkPlugin) { + this.cloudflareThinkPlugin.disable(); + this.cloudflareThinkPlugin = null; + } + if (this.cursorSDKPlugin) { this.cursorSDKPlugin.disable(); this.cursorSDKPlugin = null; diff --git a/js/src/instrumentation/config.ts b/js/src/instrumentation/config.ts index 8a2d43373..cbb9ffc7c 100644 --- a/js/src/instrumentation/config.ts +++ b/js/src/instrumentation/config.ts @@ -8,6 +8,7 @@ export interface InstrumentationIntegrationsConfig { googleADK?: boolean; huggingface?: boolean; claudeAgentSDK?: boolean; + cloudflareThink?: boolean; cursor?: boolean; cursorSDK?: boolean; flue?: boolean; @@ -65,6 +66,7 @@ const envIntegrationAliases: Record< vercel: "vercel", claudeagentsdk: "claudeAgentSDK", "claude-agent-sdk": "claudeAgentSDK", + cloudflarethink: "cloudflareThink", cursor: "cursor", "cursor-sdk": "cursorSDK", cursorsdk: "cursorSDK", @@ -121,6 +123,7 @@ export function getDefaultInstrumentationIntegrations(): Record< googleADK: true, huggingface: true, claudeAgentSDK: true, + cloudflareThink: true, cursor: true, cursorSDK: true, flue: true, diff --git a/js/src/instrumentation/plugins/ai-sdk-plugin.ts b/js/src/instrumentation/plugins/ai-sdk-plugin.ts index 14d581c3e..49d3f13ab 100644 --- a/js/src/instrumentation/plugins/ai-sdk-plugin.ts +++ b/js/src/instrumentation/plugins/ai-sdk-plugin.ts @@ -28,6 +28,7 @@ import { } from "../../wrappers/ai-sdk/workflow-agent-context"; import { zodToJsonSchema } from "../../zod/utils"; import { aiSDKChannels, harnessAgentChannels } from "./ai-sdk-channels"; +import { currentCloudflareThinkSpan } from "./cloudflare-think-context"; import type { AISDK, AISDKCallParams, @@ -198,6 +199,7 @@ export class AISDKPlugin extends BasePlugin { traceStreamingChannel(aiSDKChannels.streamText, { name: "streamText", type: SpanTypeAttribute.FUNCTION, + shouldTrace: () => currentCloudflareThinkSpan() === undefined, extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths), extractOutput: (result, endEvent) => @@ -224,6 +226,7 @@ export class AISDKPlugin extends BasePlugin { traceSyncStreamChannel(aiSDKChannels.streamTextSync, { name: "streamText", type: SpanTypeAttribute.FUNCTION, + shouldTrace: () => currentCloudflareThinkSpan() === undefined, extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths), patchResult: ({ endEvent, result, span, startTime }) => @@ -1361,6 +1364,43 @@ function prepareAISDKWorkflowAgentStreamInput( }; } +/** + * Prepares an AI SDK stream owned by an outer agent framework span. + * The framework owns the parent span lifecycle while AI SDK model and tool + * calls are attached directly beneath it. + */ +export function prepareAISDKAgentCallInput( + params: AISDKCallParams, + event: { + aiSDK?: AISDK; + denyOutputPaths?: string[]; + self?: unknown; + [key: string]: unknown; + }, + span: Span, + defaultDenyOutputPaths: string[] = DEFAULT_DENY_OUTPUT_PATHS, +): { + input: unknown; + metadata: Record; +} { + const { input } = processAISDKWorkflowAgentCallInput(params); + const metadata = extractMetadataFromCallParams(params, event.self); + const childTracing = prepareAISDKChildTracing( + params, + event.self, + span, + defaultDenyOutputPaths, + event.aiSDK, + { agentOwner: true }, + ); + event.modelWrapped = childTracing.modelWrapped; + if (childTracing.cleanup) { + event.__braintrust_ai_sdk_cleanup = childTracing.cleanup; + } + + return { input, metadata }; +} + function prepareAISDKEmbedInput( params: AISDKEmbedParams, self?: unknown, @@ -1408,6 +1448,22 @@ function extractTopLevelAISDKMetrics( return metrics; } +async function extractResolvedAISDKTokenMetrics( + result: AISDKResult, +): Promise> { + for (const field of ["totalUsage", "usage"] as const) { + try { + const usage = await Promise.resolve(result[field]); + if (usage !== undefined) { + return extractTokenMetrics({ [field]: usage } as AISDKResult); + } + } catch { + // Fall back to the next usage field or the synchronous extractor. + } + } + return extractTokenMetrics(result); +} + function hasModelChildTracing(event?: { [key: string]: unknown }): boolean { return ( event?.modelWrapped === true || @@ -1870,7 +1926,7 @@ function closeOpenAISDKModelPatchSpans(entry: AISDKModelPatchEntry): void { entry.openSpans.clear(); } -function prepareAISDKChildTracing( +export function prepareAISDKChildTracing( params: AISDKCallParams, self: unknown, parentSpan: Span, @@ -2418,7 +2474,9 @@ function prepareAISDKChildTracing( }; } -function finalizeAISDKChildTracing(event?: { [key: string]: unknown }): void { +export function finalizeAISDKChildTracing(event?: { + [key: string]: unknown; +}): void { const cleanup = event?.__braintrust_ai_sdk_cleanup; if (event && typeof cleanup === "function") { cleanup(); @@ -2557,23 +2615,27 @@ function isAISDKContentAsyncIterableChunk(chunk: unknown): boolean { return isObject(part) && typeof part.type !== "string"; } -function patchAISDKStreamingResult(args: { +export function patchAISDKStreamingResult(args: { defaultDenyOutputPaths: string[]; endEvent: { denyOutputPaths?: string[]; [key: string]: unknown }; + forceTopLevelMetrics?: boolean; onComplete?: () => void; result: AISDKResult; resolvePromiseUsage?: boolean; span: Span; startTime: number; + transformOutput?: (output: unknown) => unknown; }): boolean { const { defaultDenyOutputPaths, endEvent, + forceTopLevelMetrics, onComplete, result, resolvePromiseUsage, span, startTime, + transformOutput, } = args; if (!result || typeof result !== "object") { @@ -2600,8 +2662,10 @@ function patchAISDKStreamingResult(args: { outputLogged = true; try { - const metrics = extractTopLevelAISDKMetrics(result, endEvent); - if (resolvePromiseUsage) { + const metrics = forceTopLevelMetrics + ? await extractResolvedAISDKTokenMetrics(result) + : extractTopLevelAISDKMetrics(result, endEvent); + if (resolvePromiseUsage && !forceTopLevelMetrics) { try { const resultRecord = result as Record; const pendingUsage = resultRecord.totalUsage ?? resultRecord.usage; @@ -2625,10 +2689,13 @@ function patchAISDKStreamingResult(args: { metrics.time_to_first_token = firstChunkTime - startTime; } - const output = await processAISDKStreamingOutput( + const processedOutput = await processAISDKStreamingOutput( result, resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths), ); + const output = transformOutput + ? transformOutput(processedOutput) + : processedOutput; const metadata = buildResolvedMetadataPayload(result).metadata; span.log({ diff --git a/js/src/instrumentation/plugins/cloudflare-think-channels.ts b/js/src/instrumentation/plugins/cloudflare-think-channels.ts new file mode 100644 index 000000000..d97625314 --- /dev/null +++ b/js/src/instrumentation/plugins/cloudflare-think-channels.ts @@ -0,0 +1,22 @@ +import { channel, defineChannels } from "../core/channel-definitions"; +import type { + CloudflareThinkInstance, + CloudflareThinkStreamableResult, + CloudflareThinkTurnInput, +} from "../../vendor-sdk-types/cloudflare-think"; + +type CloudflareThinkChannelContext = { + self?: CloudflareThinkInstance; + moduleVersion?: string; +}; + +export const cloudflareThinkChannels = defineChannels("@cloudflare/think", { + runInferenceLoop: channel< + [CloudflareThinkTurnInput], + CloudflareThinkStreamableResult, + CloudflareThinkChannelContext + >({ + channelName: "Think.runInferenceLoop", + kind: "async", + }), +}); diff --git a/js/src/instrumentation/plugins/cloudflare-think-context.ts b/js/src/instrumentation/plugins/cloudflare-think-context.ts new file mode 100644 index 000000000..0574b543f --- /dev/null +++ b/js/src/instrumentation/plugins/cloudflare-think-context.ts @@ -0,0 +1,32 @@ +import { _internalGetGlobalState, type Span } from "../../logger"; + +const cloudflareThinkSpans = new Map(); + +export function registerCloudflareThinkSpan(span: Span): void { + if (span.spanId) { + cloudflareThinkSpans.set(span.spanId, span); + } +} + +export function unregisterCloudflareThinkSpan(span: Span): void { + if (span.spanId) { + cloudflareThinkSpans.delete(span.spanId); + } +} + +export function currentCloudflareThinkSpan(): Span | undefined { + const parentSpanIds = + _internalGetGlobalState().contextManager.getParentSpanIds()?.spanParents ?? + []; + for (const parentSpanId of parentSpanIds) { + const span = cloudflareThinkSpans.get(parentSpanId); + if (span) { + return span; + } + } + return undefined; +} + +export function cloudflareThinkSpanCountForTesting(): number { + return cloudflareThinkSpans.size; +} diff --git a/js/src/instrumentation/plugins/cloudflare-think-plugin.test.ts b/js/src/instrumentation/plugins/cloudflare-think-plugin.test.ts new file mode 100644 index 000000000..5bb337758 --- /dev/null +++ b/js/src/instrumentation/plugins/cloudflare-think-plugin.test.ts @@ -0,0 +1,158 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import * as ai from "ai"; +import { configureNode } from "../../node/config"; +import { + _exportsForTestingOnly, + initLogger, + type TestBackgroundLogger, +} from "../../logger"; +import { wrapAISDK } from "../../wrappers/ai-sdk"; +import { wrapCloudflareThink } from "../../wrappers/cloudflare-think"; +import { cloudflareThinkSpanCountForTesting } from "./cloudflare-think-context"; + +try { + configureNode(); +} catch { + // Best-effort initialization for test environments. +} + +describe("Cloudflare Think instrumentation", () => { + let backgroundLogger: TestBackgroundLogger; + + beforeAll(async () => { + await _exportsForTestingOnly.simulateLoginForTests(); + }); + + beforeEach(() => { + backgroundLogger = _exportsForTestingOnly.useTestBackgroundLogger(); + initLogger({ + projectName: "cloudflare-think-plugin.test.ts", + projectId: "test-project-id", + }); + }); + + afterEach(() => { + _exportsForTestingOnly.clearTestBackgroundLogger(); + expect(cloudflareThinkSpanCountForTesting()).toBe(0); + }); + + it("creates one task with the model call directly beneath it", async () => { + const wrappedAI = wrapAISDK(ai); + const model = makeStreamingModel("Hello from Think"); + class Think { + messages = [{ role: "user", content: "Say hello" }]; + + async _runInferenceLoop() { + return wrappedAI.streamText({ + model, + messages: this.messages, + }); + } + } + const { Think: WrappedThink } = wrapCloudflareThink({ Think }); + const result = await new WrappedThink()._runInferenceLoop(); + + let text = ""; + for await (const delta of result.textStream) { + text += delta; + } + await result.text; + expect(text).toBe("Hello from Think"); + + const spans = (await backgroundLogger.drain()) as any[]; + const task = spans.find( + (span) => span.span_attributes?.name === "Think.runTurn", + ); + const modelSpan = spans.find( + (span) => span.span_attributes?.name === "doStream", + ); + + expect(spans).toHaveLength(2); + expect(task).toMatchObject({ + span_attributes: { name: "Think.runTurn", type: "task" }, + input: [{ role: "user", content: "Say hello" }], + output: { role: "assistant", content: "Hello from Think" }, + metadata: { + braintrust: { + integration_name: "cloudflare-think", + sdk_language: "typescript", + }, + model: "think-model", + provider: "think-provider", + }, + metrics: { + completion_tokens: 4, + prompt_tokens: 3, + tokens: 7, + }, + }); + expect(modelSpan?.span_parents).toEqual([task?.span_id]); + expect( + spans.some((span) => span.span_attributes?.name === "streamText"), + ).toBe(false); + }); + + it("records failures and releases the active Think context", async () => { + const error = new Error("inference failed"); + class Think { + messages = [{ role: "user", content: "Fail now" }]; + + async _runInferenceLoop() { + throw error; + } + } + const { Think: WrappedThink } = wrapCloudflareThink({ Think }); + + await expect(new WrappedThink()._runInferenceLoop()).rejects.toBe(error); + + const spans = (await backgroundLogger.drain()) as any[]; + expect(spans).toHaveLength(1); + expect(spans[0]).toMatchObject({ + input: [{ role: "user", content: "Fail now" }], + span_attributes: { name: "Think.runTurn", type: "task" }, + }); + expect(spans[0].error).toBeDefined(); + }); +}); + +function makeStreamingModel(text: string): any { + return { + specificationVersion: "v3", + provider: "think-provider", + modelId: "think-model", + supportedUrls: {}, + doGenerate: async () => { + throw new Error("doGenerate should not be called"); + }, + doStream: async () => ({ + stream: new ReadableStream({ + start(controller) { + controller.enqueue({ type: "stream-start", warnings: [] }); + controller.enqueue({ type: "text-start", id: "text-1" }); + controller.enqueue({ type: "text-delta", id: "text-1", delta: text }); + controller.enqueue({ type: "text-end", id: "text-1" }); + controller.enqueue({ + type: "finish", + finishReason: { unified: "stop", raw: "stop" }, + usage: { + inputTokens: { + total: 3, + noCache: 3, + cacheRead: 0, + cacheWrite: 0, + }, + outputTokens: { + total: 4, + text: 4, + reasoning: 0, + }, + }, + }); + controller.close(); + }, + }), + warnings: [], + }), + }; +} diff --git a/js/src/instrumentation/plugins/cloudflare-think-plugin.ts b/js/src/instrumentation/plugins/cloudflare-think-plugin.ts new file mode 100644 index 000000000..5f68a2d14 --- /dev/null +++ b/js/src/instrumentation/plugins/cloudflare-think-plugin.ts @@ -0,0 +1,373 @@ +import { BasePlugin } from "../core"; +import type { ChannelMessage } from "../core/channel-definitions"; +import type { IsoChannelHandlers } from "../../isomorph"; +import { + BRAINTRUST_CURRENT_SPAN_STORE, + _internalGetGlobalState, + startSpan, +} from "../../logger"; +import type { CurrentSpanStore, Span } from "../../logger"; +import { debugLogger } from "../../debug-logger"; +import { getCurrentUnixTimestamp } from "../../util"; +import { SpanTypeAttribute, isObject } from "../../../util/index"; +import { isAutoInstrumentationSuppressed } from "../auto-instrumentation-suppression"; + +// Think delegates inference and tool execution to AI SDK's streamText. Its +// events keep the task open through stream consumption and provide the model, +// tool, output, and usage data that the outer Think call does not expose. +import { aiSDKChannels } from "./ai-sdk-channels"; +import { + DEFAULT_DENY_OUTPUT_PATHS, + finalizeAISDKChildTracing, + patchAISDKStreamingResult, + prepareAISDKAgentCallInput, +} from "./ai-sdk-plugin"; +import { cloudflareThinkChannels } from "./cloudflare-think-channels"; +import { + registerCloudflareThinkSpan, + unregisterCloudflareThinkSpan, +} from "./cloudflare-think-context"; +import type { AISDKResult } from "../../vendor-sdk-types/ai-sdk"; +import type { CloudflareThinkMessage } from "../../vendor-sdk-types/cloudflare-think"; + +type ThinkRunState = { + aiEvent?: Record; + aiResultPatched: boolean; + fallbackInput?: unknown; + finalized: boolean; + inputLogged: boolean; + span: Span; + startTime: number; +}; + +type AISDKStreamEvent = + | ChannelMessage + | ChannelMessage; + +const THINK_STATE_ID = Symbol.for("braintrust.cloudflare-think.state-id"); + +export class CloudflareThinkPlugin extends BasePlugin { + private readonly statesBySpanId = new Map(); + + protected onEnable(): void { + this.subscribeToThinkRuns(); + this.subscribeToAISDKStreamTextSync(); + this.subscribeToAISDKStreamTextAsync(); + } + + protected onDisable(): void { + for (const unsubscribe of this.unsubscribers) { + unsubscribe(); + } + this.unsubscribers = []; + + for (const state of this.statesBySpanId.values()) { + this.finishState(state); + } + this.statesBySpanId.clear(); + } + + private subscribeToThinkRuns(): void { + const channel = cloudflareThinkChannels.runInferenceLoop.tracingChannel(); + const states = new WeakMap(); + const state = _internalGetGlobalState(); + const contextManager = state.contextManager; + const currentSpanStore = ( + contextManager as { + [BRAINTRUST_CURRENT_SPAN_STORE]?: CurrentSpanStore; + } + )[BRAINTRUST_CURRENT_SPAN_STORE]; + + const ensureState = ( + event: ChannelMessage, + ): ThinkRunState | undefined => { + if (isAutoInstrumentationSuppressed()) { + return undefined; + } + const existing = states.get(event); + if (existing) { + return existing; + } + + const span = startSpan({ + name: "Think.runTurn", + spanAttributes: { type: SpanTypeAttribute.TASK }, + }); + const runState: ThinkRunState = { + aiResultPatched: false, + fallbackInput: extractFallbackInput(event.self?.messages), + finalized: false, + inputLogged: false, + span, + startTime: getCurrentUnixTimestamp(), + }; + const metadata: Record = { + braintrust: { + integration_name: "cloudflare-think", + sdk_language: "typescript", + }, + }; + if (typeof event.moduleVersion === "string") { + metadata["cloudflare_think.version"] = event.moduleVersion; + } + span.log({ metadata }); + states.set(event, runState); + if (span.spanId) { + this.statesBySpanId.set(span.spanId, runState); + } + registerCloudflareThinkSpan(span); + return runState; + }; + + if (currentSpanStore && channel.start) { + channel.start.bindStore(currentSpanStore, (event) => { + const runState = ensureState(event); + return runState + ? contextManager.wrapSpanForStore(runState.span) + : currentSpanStore.getStore(); + }); + this.unsubscribers.push(() => + channel.start?.unbindStore(currentSpanStore), + ); + } + + const handlers: IsoChannelHandlers< + ChannelMessage + > = { + start: (event) => { + ensureState(event); + }, + asyncEnd: (event) => { + const runState = states.get(event); + states.delete(event); + if (!runState || runState.finalized || runState.aiResultPatched) { + return; + } + this.finishState(runState, undefined, event.result); + }, + error: (event) => { + const runState = states.get(event); + states.delete(event); + if (runState) { + this.finishState(runState, event.error); + } + }, + }; + + channel.subscribe(handlers); + this.unsubscribers.push(() => channel.unsubscribe(handlers)); + } + + private subscribeToAISDKStreamTextSync(): void { + const channel = aiSDKChannels.streamTextSync.tracingChannel(); + const handlers: IsoChannelHandlers< + ChannelMessage + > = { + start: (event) => { + this.startAISDKStream(event); + }, + end: (event) => { + this.endAISDKStream(event); + }, + error: (event) => { + this.errorAISDKStream(event); + }, + }; + + channel.subscribe(handlers); + this.unsubscribers.push(() => channel.unsubscribe(handlers)); + } + + private subscribeToAISDKStreamTextAsync(): void { + const channel = aiSDKChannels.streamText.tracingChannel(); + const handlers: IsoChannelHandlers< + ChannelMessage + > = { + start: (event) => { + this.startAISDKStream(event); + }, + asyncEnd: (event) => { + this.endAISDKStream(event); + }, + error: (event) => { + this.errorAISDKStream(event); + }, + }; + + channel.subscribe(handlers); + this.unsubscribers.push(() => channel.unsubscribe(handlers)); + } + + private startAISDKStream(event: AISDKStreamEvent): void { + const runState = this.currentState(); + if (!runState || runState.finalized) { + return; + } + + try { + const prepared = prepareAISDKAgentCallInput( + event.arguments[0], + event, + runState.span, + ); + runState.span.log({ + input: extractThinkTaskInput(prepared.input), + metadata: { + ...prepared.metadata, + braintrust: { + integration_name: "cloudflare-think", + sdk_language: "typescript", + }, + }, + }); + runState.inputLogged = true; + runState.aiEvent = event; + Reflect.set(event, THINK_STATE_ID, runState.span.spanId); + } catch (error) { + debugLogger.error( + "Error preparing @cloudflare/think AI SDK tracing:", + error, + ); + } + } + + private endAISDKStream(event: AISDKStreamEvent): void { + const runState = this.stateForAISDKEvent(event); + if (!runState || runState.finalized) { + return; + } + + const patched = patchAISDKStreamingResult({ + defaultDenyOutputPaths: DEFAULT_DENY_OUTPUT_PATHS, + endEvent: event, + forceTopLevelMetrics: true, + onComplete: () => this.releaseState(runState), + result: event.result as AISDKResult, + span: runState.span, + startTime: runState.startTime, + transformOutput: extractThinkTaskOutput, + }); + runState.aiResultPatched = patched; + if (!patched) { + this.finishState(runState, undefined, event.result); + } + } + + private errorAISDKStream(event: AISDKStreamEvent): void { + const runState = this.stateForAISDKEvent(event); + if (runState) { + this.finishState(runState, event.error); + } + } + + private currentState(): ThinkRunState | undefined { + const parentIds = + _internalGetGlobalState().contextManager.getParentSpanIds() + ?.spanParents ?? []; + for (const parentId of parentIds) { + const state = this.statesBySpanId.get(parentId); + if (state) { + return state; + } + } + return undefined; + } + + private stateForAISDKEvent(event: object): ThinkRunState | undefined { + const spanId = Reflect.get(event, THINK_STATE_ID); + return typeof spanId === "string" + ? this.statesBySpanId.get(spanId) + : undefined; + } + + private finishState( + state: ThinkRunState, + error?: unknown, + output?: unknown, + ): void { + if (state.finalized) { + return; + } + state.finalized = true; + try { + if (!state.inputLogged && state.fallbackInput !== undefined) { + state.span.log({ input: state.fallbackInput }); + } + if (error !== undefined) { + state.span.log({ error }); + } else if (output !== undefined) { + state.span.log({ output: extractThinkTaskOutput(output) }); + } + finalizeAISDKChildTracing(state.aiEvent); + state.span.end(); + } finally { + this.releaseState(state); + } + } + + private releaseState(state: ThinkRunState): void { + state.finalized = true; + unregisterCloudflareThinkSpan(state.span); + if (state.span.spanId) { + this.statesBySpanId.delete(state.span.spanId); + } + } +} + +function extractFallbackInput( + messages: CloudflareThinkMessage[] | undefined, +): unknown { + if (!Array.isArray(messages) || messages.length === 0) { + return undefined; + } + let latestUserIndex = -1; + for (let index = messages.length - 1; index >= 0; index--) { + if (messages[index]?.role === "user") { + latestUserIndex = index; + break; + } + } + const selected = latestUserIndex >= 0 ? messages.slice(latestUserIndex) : []; + return selected.map((message) => ({ + role: message.role, + content: message.content ?? message.parts, + })); +} + +function extractThinkTaskOutput(output: unknown): unknown { + if (!isObject(output)) { + return output; + } + if (typeof output.text === "string") { + return { role: "assistant", content: output.text }; + } + if (output.object !== undefined) { + return output.object; + } + return output; +} + +function extractThinkTaskInput(input: unknown): unknown { + if (!isObject(input)) { + return input; + } + + const system = input.instructions ?? input.system; + if (Array.isArray(input.messages)) { + return system === undefined + ? input.messages + : [{ role: "system", content: system }, ...input.messages]; + } + if (Array.isArray(input.prompt)) { + return system === undefined + ? input.prompt + : [{ role: "system", content: system }, ...input.prompt]; + } + if (typeof input.prompt === "string") { + const messages = [{ role: "user", content: input.prompt }]; + return system === undefined + ? messages + : [{ role: "system", content: system }, ...messages]; + } + return input; +} diff --git a/js/src/vendor-sdk-types/cloudflare-think.ts b/js/src/vendor-sdk-types/cloudflare-think.ts new file mode 100644 index 000000000..7a5130c05 --- /dev/null +++ b/js/src/vendor-sdk-types/cloudflare-think.ts @@ -0,0 +1,31 @@ +// @cloudflare/think types + +export type CloudflareThinkMessage = { + role?: string; + parts?: unknown[]; + content?: unknown; +}; + +export type CloudflareThinkTurnInput = { + continuation?: boolean; + body?: unknown; +}; + +export type CloudflareThinkStreamableResult = { + toUIMessageStream?: (...args: unknown[]) => unknown; +}; + +export type CloudflareThinkInstance = { + messages?: CloudflareThinkMessage[]; + _runInferenceLoop?: ( + input: CloudflareThinkTurnInput, + ) => Promise; +}; + +export type CloudflareThinkConstructor = { + prototype: CloudflareThinkInstance & Record; +}; + +export type CloudflareThinkModule = { + Think?: CloudflareThinkConstructor; +}; diff --git a/js/src/wrappers/cloudflare-think.test.ts b/js/src/wrappers/cloudflare-think.test.ts new file mode 100644 index 000000000..1db1b0f5d --- /dev/null +++ b/js/src/wrappers/cloudflare-think.test.ts @@ -0,0 +1,91 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; + +const { tracePromise } = vi.hoisted(() => ({ + tracePromise: vi.fn((fn: () => unknown, _event?: unknown) => fn()), +})); + +vi.mock("../isomorph", () => ({ + default: { + newTracingChannel: vi.fn(() => ({ + subscribe: vi.fn(), + tracePromise, + unsubscribe: vi.fn(), + })), + }, +})); + +import { wrapCloudflareThink } from "./cloudflare-think"; + +describe("wrapCloudflareThink", () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + it.each([null, undefined, "think", {}, { Think: class {} }])( + "returns unsupported module %j unchanged", + (sdk) => { + expect(wrapCloudflareThink(sdk)).toBe(sdk); + expect(tracePromise).not.toHaveBeenCalled(); + }, + ); + + it("traces _runInferenceLoop without changing its result or receiver", async () => { + class Think { + readonly marker = "think-instance"; + + async _runInferenceLoop(input: { body: unknown }) { + return { input, marker: this.marker }; + } + } + const sdk = { Think, helper: () => "unchanged" }; + + expect(wrapCloudflareThink(sdk)).toBe(sdk); + const instance = new sdk.Think(); + const input = { body: { messages: [] } }; + await expect(instance._runInferenceLoop(input)).resolves.toEqual({ + input, + marker: "think-instance", + }); + expect(tracePromise).toHaveBeenCalledTimes(1); + expect(tracePromise.mock.calls[0]?.[1]).toEqual({ + arguments: [input], + self: instance, + }); + expect(sdk.helper()).toBe("unchanged"); + }); + + it("is idempotent", async () => { + class Think { + async _runInferenceLoop(input: unknown) { + return input; + } + } + const sdk = { Think }; + + wrapCloudflareThink(wrapCloudflareThink(sdk)); + await new sdk.Think()._runInferenceLoop("hello"); + + expect(tracePromise).toHaveBeenCalledTimes(1); + }); + + it("preserves the original method descriptor", () => { + class Think {} + const original = vi.fn(async () => "ok"); + Object.defineProperty(Think.prototype, "_runInferenceLoop", { + configurable: true, + enumerable: false, + value: original, + writable: false, + }); + + wrapCloudflareThink({ Think }); + + expect( + Object.getOwnPropertyDescriptor(Think.prototype, "_runInferenceLoop"), + ).toMatchObject({ + configurable: true, + enumerable: false, + writable: false, + }); + }); +}); diff --git a/js/src/wrappers/cloudflare-think.ts b/js/src/wrappers/cloudflare-think.ts new file mode 100644 index 000000000..9c04400ce --- /dev/null +++ b/js/src/wrappers/cloudflare-think.ts @@ -0,0 +1,75 @@ +import { cloudflareThinkChannels } from "../instrumentation/plugins/cloudflare-think-channels"; +import type { + CloudflareThinkConstructor, + CloudflareThinkInstance, + CloudflareThinkModule, + CloudflareThinkTurnInput, +} from "../vendor-sdk-types/cloudflare-think"; + +const WRAPPED_THINK = Symbol.for("braintrust.cloudflare-think.wrapped"); + +/** + * Adds Braintrust tracing to an `@cloudflare/think` module when build-time + * auto-instrumentation is unavailable. + * + * @example + * ```ts + * import * as cloudflareThink from "@cloudflare/think"; + * import { wrapCloudflareThink } from "braintrust"; + * + * const { Think } = wrapCloudflareThink(cloudflareThink); + * ``` + */ +export function wrapCloudflareThink(sdk: T): T { + if (!sdk || typeof sdk !== "object") { + return sdk; + } + + const thinkModule = sdk as T & CloudflareThinkModule; + if (typeof thinkModule.Think !== "function") { + return sdk; + } + + patchThinkClass(thinkModule.Think); + return sdk; +} + +function patchThinkClass(Think: CloudflareThinkConstructor): void { + const prototype = Think.prototype; + if (!prototype || prototype[WRAPPED_THINK]) { + return; + } + + const descriptor = Object.getOwnPropertyDescriptor( + prototype, + "_runInferenceLoop", + ); + if (!descriptor || typeof descriptor.value !== "function") { + return; + } + + const original = descriptor.value as NonNullable< + CloudflareThinkInstance["_runInferenceLoop"] + >; + Object.defineProperty(prototype, "_runInferenceLoop", { + ...descriptor, + value: function wrappedCloudflareThinkRunInferenceLoop( + this: CloudflareThinkInstance, + input: CloudflareThinkTurnInput, + ) { + const args = [input] as [CloudflareThinkTurnInput]; + return cloudflareThinkChannels.runInferenceLoop.tracePromise( + () => Reflect.apply(original, this, args), + { + arguments: args, + self: this, + }, + ); + }, + }); + Object.defineProperty(prototype, WRAPPED_THINK, { + configurable: false, + enumerable: false, + value: true, + }); +} From 47132b395c3840adb8ca9c192a80d786d55beffd Mon Sep 17 00:00:00 2001 From: lforst <8118419+lforst@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:44:36 +0000 Subject: [PATCH 2/3] fix --- js/src/instrumentation/plugins/ai-sdk-plugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/instrumentation/plugins/ai-sdk-plugin.ts b/js/src/instrumentation/plugins/ai-sdk-plugin.ts index 49d3f13ab..6ddf173b1 100644 --- a/js/src/instrumentation/plugins/ai-sdk-plugin.ts +++ b/js/src/instrumentation/plugins/ai-sdk-plugin.ts @@ -1926,7 +1926,7 @@ function closeOpenAISDKModelPatchSpans(entry: AISDKModelPatchEntry): void { entry.openSpans.clear(); } -export function prepareAISDKChildTracing( +function prepareAISDKChildTracing( params: AISDKCallParams, self: unknown, parentSpan: Span, From a14e46575473f3f2083fc775ce7cd3424dd52de3 Mon Sep 17 00:00:00 2001 From: lforst <8118419+lforst@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:54:22 +0000 Subject: [PATCH 3/3] fix ci --- .../plugins/cloudflare-think-context.ts | 2 +- .../plugins/cloudflare-think-plugin.ts | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/js/src/instrumentation/plugins/cloudflare-think-context.ts b/js/src/instrumentation/plugins/cloudflare-think-context.ts index 0574b543f..74c9fc6dd 100644 --- a/js/src/instrumentation/plugins/cloudflare-think-context.ts +++ b/js/src/instrumentation/plugins/cloudflare-think-context.ts @@ -16,7 +16,7 @@ export function unregisterCloudflareThinkSpan(span: Span): void { export function currentCloudflareThinkSpan(): Span | undefined { const parentSpanIds = - _internalGetGlobalState().contextManager.getParentSpanIds()?.spanParents ?? + _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? []; for (const parentSpanId of parentSpanIds) { const span = cloudflareThinkSpans.get(parentSpanId); diff --git a/js/src/instrumentation/plugins/cloudflare-think-plugin.ts b/js/src/instrumentation/plugins/cloudflare-think-plugin.ts index 5f68a2d14..559044913 100644 --- a/js/src/instrumentation/plugins/cloudflare-think-plugin.ts +++ b/js/src/instrumentation/plugins/cloudflare-think-plugin.ts @@ -71,12 +71,14 @@ export class CloudflareThinkPlugin extends BasePlugin { const channel = cloudflareThinkChannels.runInferenceLoop.tracingChannel(); const states = new WeakMap(); const state = _internalGetGlobalState(); - const contextManager = state.contextManager; - const currentSpanStore = ( - contextManager as { - [BRAINTRUST_CURRENT_SPAN_STORE]?: CurrentSpanStore; - } - )[BRAINTRUST_CURRENT_SPAN_STORE]; + const contextManager = state?.contextManager; + const currentSpanStore = contextManager + ? ( + contextManager as { + [BRAINTRUST_CURRENT_SPAN_STORE]?: CurrentSpanStore; + } + )[BRAINTRUST_CURRENT_SPAN_STORE] + : undefined; const ensureState = ( event: ChannelMessage, @@ -119,7 +121,7 @@ export class CloudflareThinkPlugin extends BasePlugin { return runState; }; - if (currentSpanStore && channel.start) { + if (contextManager && currentSpanStore && channel.start) { channel.start.bindStore(currentSpanStore, (event) => { const runState = ensureState(event); return runState @@ -262,7 +264,7 @@ export class CloudflareThinkPlugin extends BasePlugin { private currentState(): ThinkRunState | undefined { const parentIds = - _internalGetGlobalState().contextManager.getParentSpanIds() + _internalGetGlobalState()?.contextManager.getParentSpanIds() ?.spanParents ?? []; for (const parentId of parentIds) { const state = this.statesBySpanId.get(parentId);