diff --git a/.changeset/agentaos-cli-merchant.md b/.changeset/agentaos-cli-merchant.md new file mode 100644 index 0000000..6277df0 --- /dev/null +++ b/.changeset/agentaos-cli-merchant.md @@ -0,0 +1,10 @@ +--- +"agentaos": major +--- + +The `agentaos` / `agenta` CLI is now the merchant's CLI and MCP server for AgentaOS payments. + +- Removed the self-custody crypto-wallet surface: `send`, `sign`, `balance`, `receive`, `deploy`, `x402`, signer and network management, and the seventeen token-moving MCP tools. Scripts that relied on them must pin `agentaos@2`. +- The CLI now covers onboarding and money: `login` (browser approval), `status`, `audit`, `verify`, `products`, `pay`, `subscriptions`. +- The MCP server (run the binary with no arguments from an agent) exposes the seven `agenta_pay_*` tools against `AGENTAOS_GATEWAY_KEY`; the same tools are exported as `agentaos/mcp` (`registerPayTools(server, getClient)`) for hosted servers. +- A refused key tells the merchant it may have been revoked in AgentaOS and how to reconnect. diff --git a/packages/mcp-remote/.dev.vars.example b/packages/mcp-remote/.dev.vars.example new file mode 100644 index 0000000..745f57f --- /dev/null +++ b/packages/mcp-remote/.dev.vars.example @@ -0,0 +1,2 @@ +AGENTAOS_API_URL=http://localhost:8080 +MCP_PUBLIC_URL=https://localhost:8788 diff --git a/packages/mcp-remote/.gitignore b/packages/mcp-remote/.gitignore new file mode 100644 index 0000000..6bf8e87 --- /dev/null +++ b/packages/mcp-remote/.gitignore @@ -0,0 +1,2 @@ +.dev.vars +.wrangler/ diff --git a/packages/mcp-remote/README.md b/packages/mcp-remote/README.md new file mode 100644 index 0000000..6ba0497 --- /dev/null +++ b/packages/mcp-remote/README.md @@ -0,0 +1,72 @@ +# @agentaos/mcp-remote + +The AgentaOS remote MCP server: a Cloudflare Worker at `https://mcp.agentaos.ai/mcp` +that lets ChatGPT, Claude.ai, Claude Desktop and any other hosted MCP client use the +same seven `agenta_pay_*` merchant tools the `agentaos` CLI serves over stdio. + +Hosted assistants speak OAuth 2.1 to the MCP server. `@cloudflare/workers-oauth-provider` +implements that front door; the AgentaOS device-code approval page is the consent step. +No new platform endpoints, no new auth mechanism. + +## Flow + +1. The assistant hits `/mcp` without a token and discovers `/authorize`. +2. `/authorize` starts a device-code login on the platform, parks the OAuth request in KV + under a random `state`, and redirects the merchant to the existing approve page. +3. The merchant signs in if needed, picks Test or Live, and approves. +4. The approve page returns the merchant to `/callback?state=…&mode=test|live`. +5. `/callback` redeems the device code for a one-shot session, mints a secret key for the + chosen mode's networks, drops the session, and stores only the key in the grant. +6. The assistant exchanges the code at `/token`; every tool call runs with that key. + +Revoking the key on the Developers tab disconnects the assistant. The Pay SDK has no +custom-fetch hook, so after a revoke the tools surface the API's own 401 message rather +than a dedicated "reconnect" sentence. + +## Local development + +The OAuth provider only accepts an `https` issuer, so the local Worker serves TLS on a +self-signed certificate and is reached as `https://localhost:8788` (the `dev` script +passes `--local-protocol https --host localhost:8788`; without `--host`, wrangler +rewrites local requests to the production route and the issuer comes out wrong). + +```bash +cp .dev.vars.example .dev.vars # local API on :8080, public URL https://localhost:8788 +pnpm --filter agentaos build # the Worker imports the tools from agentaos/mcp +pnpm --filter @agentaos/mcp-remote dev +npx @modelcontextprotocol/inspector@latest # connect to https://localhost:8788/mcp +``` + +The approve page honours `return` for `http(s)://localhost:*` in dev, so the whole flow +runs against the local API and app. Open `https://localhost:8788/` in the browser once +and accept the certificate, or the redirect back to `/callback` stops at the warning. + +## Deploy + +```bash +wrangler login +wrangler kv namespace create OAUTH_KV # paste the id into wrangler.jsonc +wrangler deploy # binds the custom domain mcp.agentaos.ai +``` + +## Connecting an assistant + +- **ChatGPT**: Settings → Connectors → add `https://mcp.agentaos.ai/mcp`, then Approve on + the AgentaOS page that opens. +- **Claude.ai / Claude Desktop**: Customize → Connectors → Add custom connector with the + same URL, then Approve. + +## Disconnecting + +Revoke the key on app.agentaos.ai → Developers. Its name carries the key prefix the +connection was issued with. + +## Tests + +```bash +pnpm --filter @agentaos/mcp-remote test +``` + +The tests run on Node with a fake platform API, a fake KV and a fake OAuth helper. +`vitest.config.ts` aliases `cloudflare:workers` to a stub because the OAuth provider +imports it at module load. diff --git a/packages/mcp-remote/package.json b/packages/mcp-remote/package.json new file mode 100644 index 0000000..0b126c6 --- /dev/null +++ b/packages/mcp-remote/package.json @@ -0,0 +1,29 @@ +{ + "name": "@agentaos/mcp-remote", + "version": "0.1.0", + "private": true, + "description": "AgentaOS remote MCP server for ChatGPT, Claude.ai and other hosted assistants (Cloudflare Worker)", + "license": "Apache-2.0", + "type": "module", + "scripts": { + "dev": "wrangler dev --local-protocol https --host localhost:8788", + "deploy": "wrangler deploy", + "build": "tsc --noEmit", + "test": "vitest run", + "typecheck": "tsc --noEmit", + "lint": "biome check src/" + }, + "dependencies": { + "@agentaos/pay": "workspace:^", + "@cloudflare/workers-oauth-provider": "^0.10.3", + "@modelcontextprotocol/sdk": "^1.26.0", + "agentaos": "workspace:^", + "zod": "^3.24.0" + }, + "devDependencies": { + "@cloudflare/workers-types": "^5.20260908.1", + "typescript": "^5.6.0", + "vitest": "^2.0.0", + "wrangler": "^4.130.0" + } +} diff --git a/packages/mcp-remote/src/__tests__/authorize.test.ts b/packages/mcp-remote/src/__tests__/authorize.test.ts new file mode 100644 index 0000000..f39bcfe --- /dev/null +++ b/packages/mcp-remote/src/__tests__/authorize.test.ts @@ -0,0 +1,215 @@ +import type { AuthRequest, CompleteAuthorizationOptions } from '@cloudflare/workers-oauth-provider'; +import { describe, expect, it } from 'vitest'; + +import { AgentaosApi } from '../agentaos-api.js'; +import { handleAuthorize, handleCallback } from '../authorize.js'; +import type { Env } from '../env.js'; + +const API = 'http://api.test'; +const PUBLIC = 'http://mcp.test'; +const RAW_KEY = 'sk_test_rawsecret'; + +const authRequest: AuthRequest = { + responseType: 'code', + clientId: 'client-1', + redirectUri: 'https://chatgpt.com/cb', + scope: ['agentaos'], + state: 'client-state', + codeChallenge: 'abc', + codeChallengeMethod: 'S256', +}; + +function json(body: unknown, status = 200): Response { + return new Response(JSON.stringify(body), { + status, + headers: { 'content-type': 'application/json' }, + }); +} + +interface Scenario { + pollStatus: 'completed' | 'denied' | 'expired'; +} + +function fakeFetch(scenario: Scenario, calls: { url: string; init?: RequestInit }[]): typeof fetch { + return (async (input: string | URL | Request, init?: RequestInit) => { + const url = String(input); + calls.push({ url, init }); + if (url.endsWith('/auth/device-code')) { + return json({ + deviceCode: 'dev-1', + userCode: 'A7KM-X9RD', + verificationUrl: 'http://app.test/cli-auth?code=A7KM-X9RD', + expiresIn: 600, + interval: 5, + }); + } + if (url.endsWith('/auth/device-code/poll')) { + return scenario.pollStatus === 'completed' + ? json({ status: 'completed', token: 'session-jwt', email: 'm@example.com' }) + : json({ status: scenario.pollStatus }); + } + if (url.endsWith('/networks')) { + return json([ + { name: 'base', isTestnet: false }, + { name: 'base-sepolia', isTestnet: true }, + { name: 'arbitrum', isTestnet: false }, + ]); + } + if (url.endsWith('/gateway/secret-keys')) { + return json({ id: 'key-1', key_prefix: 'sk_test_raws', rawKey: RAW_KEY }); + } + return new Response('unexpected', { status: 500 }); + }) as typeof fetch; +} + +function fakeKv(): KVNamespace { + const store = new Map(); + return { + put: async (key: string, value: string) => { + store.set(key, value); + }, + get: async (key: string) => store.get(key) ?? null, + delete: async (key: string) => { + store.delete(key); + }, + } as unknown as KVNamespace; +} + +function fakeEnv(completed: CompleteAuthorizationOptions[]): Env { + return { + OAUTH_KV: fakeKv(), + OAUTH_PROVIDER: { + parseAuthRequest: async () => authRequest, + lookupClient: async () => ({ clientId: 'client-1', redirectUris: [], clientName: 'ChatGPT' }), + completeAuthorization: async (options: CompleteAuthorizationOptions) => { + completed.push(options); + return { redirectTo: 'https://chatgpt.com/cb?code=1' }; + }, + } as unknown as Env['OAUTH_PROVIDER'], + AGENTAOS_API_URL: API, + MCP_PUBLIC_URL: PUBLIC, + }; +} + +describe('remote MCP authorization', () => { + let env: Env; + let completed: CompleteAuthorizationOptions[]; + let calls: { url: string; init?: RequestInit }[]; + + function setup(scenario: Scenario = { pollStatus: 'completed' }) { + calls = []; + completed = []; + env = fakeEnv(completed); + return new AgentaosApi(API, fakeFetch(scenario, calls)); + } + + async function authorize(api: AgentaosApi): Promise { + const response = await handleAuthorize({ + request: new Request(`${PUBLIC}/authorize?client_id=client-1`), + env, + api, + }); + expect(response.status).toBe(302); + const location = new URL(response.headers.get('location') ?? ''); + return new URL(location.searchParams.get('return') ?? '').searchParams.get('state') ?? ''; + } + + function callback(api: AgentaosApi, state: string, mode: string) { + return handleCallback({ + request: new Request(`${PUBLIC}/callback?state=${state}&mode=${mode}`), + env, + api, + }); + } + + it('redirects to the approve page with return and client, keeping the user code', async () => { + const api = setup(); + const response = await handleAuthorize({ + request: new Request(`${PUBLIC}/authorize?client_id=client-1`), + env, + api, + }); + const location = new URL(response.headers.get('location') ?? ''); + expect(location.origin + location.pathname).toBe('http://app.test/cli-auth'); + expect(location.searchParams.get('code')).toBe('A7KM-X9RD'); + expect(location.searchParams.get('client')).toBe('ChatGPT'); + expect(location.searchParams.get('return')).toMatch(/^http:\/\/mcp\.test\/callback\?state=/); + }); + + it('stores the handoff so the callback can find the device code', async () => { + const api = setup(); + const state = await authorize(api); + const stored = await env.OAUTH_KV.get(`handoff:${state}`); + expect(JSON.parse(stored ?? '{}')).toMatchObject({ + deviceCode: 'dev-1', + clientName: 'ChatGPT', + authRequest, + }); + }); + + it('mints a test key from testnet networks only and completes authorization', async () => { + const api = setup(); + const state = await authorize(api); + const response = await callback(api, state, 'test'); + expect(response.status).toBe(302); + expect(response.headers.get('location')).toBe('https://chatgpt.com/cb?code=1'); + + const keyCall = calls.find((c) => c.url.endsWith('/gateway/secret-keys')); + expect(JSON.parse(String(keyCall?.init?.body))).toEqual({ + supportedNetworks: ['base-sepolia'], + label: 'ChatGPT', + }); + expect(new Headers(keyCall?.init?.headers).get('authorization')).toBe('Bearer session-jwt'); + + expect(completed).toHaveLength(1); + expect(completed[0]).toMatchObject({ + request: authRequest, + userId: 'm@example.com', + scope: ['agentaos'], + metadata: { clientName: 'ChatGPT', keyId: 'key-1', keyPrefix: 'sk_test_raws' }, + props: { apiKey: RAW_KEY, keyPrefix: 'sk_test_raws', mode: 'test' }, + }); + }); + + it('picks mainnet networks for a live connection', async () => { + const api = setup(); + const state = await authorize(api); + await callback(api, state, 'live'); + const keyCall = calls.find((c) => c.url.endsWith('/gateway/secret-keys')); + expect(JSON.parse(String(keyCall?.init?.body))).toEqual({ + supportedNetworks: ['base', 'arbitrum'], + label: 'ChatGPT', + }); + expect(completed[0]?.props).toMatchObject({ mode: 'live' }); + }); + + it('rejects an unknown state with 404', async () => { + const api = setup(); + const response = await callback(api, 'nope', 'test'); + expect(response.status).toBe(404); + }); + + it('rejects an unknown mode with 400', async () => { + const api = setup(); + const state = await authorize(api); + const response = await callback(api, state, 'staging'); + expect(response.status).toBe(400); + }); + + it('answers a denied approval with 400 and never mints a key', async () => { + const api = setup({ pollStatus: 'denied' }); + const state = await authorize(api); + const response = await callback(api, state, 'test'); + expect(response.status).toBe(400); + expect(calls.some((c) => c.url.endsWith('/gateway/secret-keys'))).toBe(false); + expect(completed).toHaveLength(0); + }); + + it('uses the handoff once: a second callback with the same state is 404', async () => { + const api = setup(); + const state = await authorize(api); + await callback(api, state, 'test'); + const second = await callback(api, state, 'test'); + expect(second.status).toBe(404); + }); +}); diff --git a/packages/mcp-remote/src/__tests__/cloudflare-workers.stub.ts b/packages/mcp-remote/src/__tests__/cloudflare-workers.stub.ts new file mode 100644 index 0000000..68d5d22 --- /dev/null +++ b/packages/mcp-remote/src/__tests__/cloudflare-workers.stub.ts @@ -0,0 +1,2 @@ +/** Node-side stand-in for the `cloudflare:workers` module (see vitest.config.ts). */ +export class WorkerEntrypoint {} diff --git a/packages/mcp-remote/src/__tests__/mcp.test.ts b/packages/mcp-remote/src/__tests__/mcp.test.ts new file mode 100644 index 0000000..3e0a098 --- /dev/null +++ b/packages/mcp-remote/src/__tests__/mcp.test.ts @@ -0,0 +1,56 @@ +import { describe, expect, it } from 'vitest'; + +import type { Env } from '../env.js'; +import { handleMcp } from '../mcp.js'; + +const EXPECTED_TOOLS = [ + 'agenta_pay_create_checkout', + 'agenta_pay_get_checkout', + 'agenta_pay_list_checkouts', + 'agenta_pay_list_subscriptions', + 'agenta_pay_cancel_subscription', + 'agenta_pay_list_customers', + 'agenta_pay_send_receipt', +]; + +const env = { + AGENTAOS_API_URL: 'http://api.test', + MCP_PUBLIC_URL: 'http://mcp.test', +} as Env; + +/** The transport answers JSON or SSE depending on negotiation; read either. */ +async function readJsonRpcResult(response: Response): Promise<{ tools: { name: string }[] }> { + const body = await response.text(); + const contentType = response.headers.get('content-type') ?? ''; + const payload = contentType.includes('text/event-stream') + ? (body + .split('\n') + .find((line) => line.startsWith('data:')) + ?.slice('data:'.length) + .trim() ?? '') + : body; + return JSON.parse(payload).result; +} + +describe('remote MCP endpoint', () => { + it('lists the seven merchant tools for a connection', async () => { + const request = new Request('http://mcp.test/mcp', { + method: 'POST', + headers: { + 'content-type': 'application/json', + accept: 'application/json, text/event-stream', + }, + body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {} }), + }); + + const response = await handleMcp(request, env, { + apiKey: 'sk_test_dummy', + keyPrefix: 'sk_test_dumm', + mode: 'test', + }); + + expect(response.status).toBe(200); + const { tools } = await readJsonRpcResult(response); + expect(tools.map((t) => t.name).sort()).toEqual([...EXPECTED_TOOLS].sort()); + }); +}); diff --git a/packages/mcp-remote/src/agentaos-api.ts b/packages/mcp-remote/src/agentaos-api.ts new file mode 100644 index 0000000..16c0239 --- /dev/null +++ b/packages/mcp-remote/src/agentaos-api.ts @@ -0,0 +1,85 @@ +const API_PREFIX = '/api/v1'; + +export interface DeviceCode { + deviceCode: string; + userCode: string; + verificationUrl: string; + expiresIn: number; + interval: number; +} + +export type DeviceCodePollStatus = 'pending' | 'completed' | 'expired' | 'denied'; + +export interface DeviceCodePoll { + status: DeviceCodePollStatus; + token?: string; + email?: string; + orgName?: string; +} + +export interface Network { + name: string; + isTestnet: boolean; +} + +export interface SecretKey { + id: string; + key_prefix: string; + rawKey: string; +} + +/** The four platform calls the connection flow needs. Throws on any non-2xx. */ +export class AgentaosApi { + constructor( + private readonly baseUrl: string, + // Wrapped, not passed bare: a bare `fetch` stored on the instance is + // invoked with the instance as `this`, which Workers reject as an + // illegal invocation. Node tolerates it, so a test would not catch it. + private readonly fetchFn: typeof fetch = (input, init) => fetch(input, init), + ) {} + + createDeviceCode(): Promise { + return this.request('POST', '/auth/device-code', {}); + } + + pollDeviceCode(deviceCode: string): Promise { + return this.request('POST', '/auth/device-code/poll', { deviceCode }); + } + + listNetworks(): Promise { + return this.request('GET', '/networks'); + } + + /** `label` is what the Developers tab shows as the key's name (max 40 chars). */ + createSecretKey( + sessionToken: string, + supportedNetworks: string[], + label: string, + ): Promise { + return this.request( + 'POST', + '/gateway/secret-keys', + { supportedNetworks, label: label.slice(0, 40) }, + { authorization: `Bearer ${sessionToken}` }, + ); + } + + private async request( + method: 'GET' | 'POST', + path: string, + body?: unknown, + headers: Record = {}, + ): Promise { + const response = await this.fetchFn(`${this.baseUrl}${API_PREFIX}${path}`, { + method, + headers: { 'content-type': 'application/json', ...headers }, + body: body === undefined ? undefined : JSON.stringify(body), + }); + if (!response.ok) { + throw new Error( + `AgentaOS API ${method} ${path} -> ${response.status}: ${await response.text()}`, + ); + } + return (await response.json()) as T; + } +} diff --git a/packages/mcp-remote/src/authorize.ts b/packages/mcp-remote/src/authorize.ts new file mode 100644 index 0000000..144ec46 --- /dev/null +++ b/packages/mcp-remote/src/authorize.ts @@ -0,0 +1,141 @@ +import { type AuthRequest, AuthorizationError } from '@cloudflare/workers-oauth-provider'; + +import type { AgentaosApi } from './agentaos-api.js'; +import type { ConnectionMode, ConnectionProps, Env } from './env.js'; + +const HANDOFF_TTL_SECONDS = 600; +const POLL_ATTEMPTS = 5; +const POLL_DELAY_MS = 1000; + +interface HandlerInput { + request: Request; + env: Env; + api: AgentaosApi; +} + +/** What /authorize stores under the state until /callback picks it up. */ +interface Handoff { + deviceCode: string; + authRequest: AuthRequest; + clientName: string; +} + +function handoffKey(state: string): string { + return `handoff:${state}`; +} + +function randomState(): string { + const bytes = crypto.getRandomValues(new Uint8Array(32)); + return btoa(String.fromCharCode(...bytes)) + .replaceAll('+', '-') + .replaceAll('/', '_') + .replace(/=+$/, ''); +} + +function text(body: string, status: number): Response { + return new Response(body, { status, headers: { 'content-type': 'text/plain; charset=utf-8' } }); +} + +function authorizationErrorResponse(error: AuthorizationError): Response { + if (!error.redirectUri) return text(error.description, 400); + const redirect = new URL(error.redirectUri); + redirect.searchParams.set('error', error.code); + redirect.searchParams.set('error_description', error.description); + if (error.state) redirect.searchParams.set('state', error.state); + if (error.issuer) redirect.searchParams.set('iss', error.issuer); + return Response.redirect(redirect.toString(), 302); +} + +/** + * The OAuth authorize endpoint. Starts a device-code login on the platform, + * parks the OAuth request in KV under a random state, and sends the merchant + * to the existing approve page with a return address back to /callback. + */ +export async function handleAuthorize({ request, env, api }: HandlerInput): Promise { + let authRequest: AuthRequest; + try { + authRequest = await env.OAUTH_PROVIDER.parseAuthRequest(request); + } catch (error) { + if (error instanceof AuthorizationError) return authorizationErrorResponse(error); + throw error; + } + + const client = await env.OAUTH_PROVIDER.lookupClient(authRequest.clientId); + if (!client) return text('Unknown OAuth client', 400); + const clientName = client.clientName ?? 'this assistant'; + + const device = await api.createDeviceCode(); + const state = randomState(); + const handoff: Handoff = { deviceCode: device.deviceCode, authRequest, clientName }; + await env.OAUTH_KV.put(handoffKey(state), JSON.stringify(handoff), { + expirationTtl: HANDOFF_TTL_SECONDS, + }); + + const approve = new URL(device.verificationUrl); + approve.searchParams.set('return', `${env.MCP_PUBLIC_URL}/callback?state=${state}`); + approve.searchParams.set('client', clientName); + return Response.redirect(approve.toString(), 302); +} + +function parseMode(value: string | null): ConnectionMode | null { + return value === 'test' || value === 'live' ? value : null; +} + +async function takeHandoff(env: Env, state: string): Promise { + const key = handoffKey(state); + const raw = await env.OAUTH_KV.get(key); + if (!raw) return null; + await env.OAUTH_KV.delete(key); + return JSON.parse(raw) as Handoff; +} + +type Approval = { token: string; email?: string } | { failure: string }; + +async function waitForApproval(api: AgentaosApi, deviceCode: string): Promise { + for (let attempt = 0; attempt < POLL_ATTEMPTS; attempt++) { + const poll = await api.pollDeviceCode(deviceCode); + if (poll.status === 'completed' && poll.token) return { token: poll.token, email: poll.email }; + if (poll.status === 'expired') + return { failure: 'This approval expired. Start the connection again.' }; + if (poll.status === 'denied') return { failure: 'The connection was declined in AgentaOS.' }; + if (attempt < POLL_ATTEMPTS - 1) await new Promise((r) => setTimeout(r, POLL_DELAY_MS)); + } + return { failure: 'AgentaOS has not confirmed the approval yet. Try connecting again.' }; +} + +/** + * Where the approve page returns the merchant. Redeems the device code for a + * one-shot session, mints the secret key that becomes the connection's only + * credential, and hands the OAuth flow back to the client. + */ +export async function handleCallback({ request, env, api }: HandlerInput): Promise { + const url = new URL(request.url); + const state = url.searchParams.get('state'); + const mode = parseMode(url.searchParams.get('mode')); + if (!state || !mode) return text('Missing state or mode.', 400); + + const handoff = await takeHandoff(env, state); + if (!handoff) return text('This approval link expired. Start the connection again.', 404); + + const approval = await waitForApproval(api, handoff.deviceCode); + if ('failure' in approval) return text(approval.failure, 400); + + const wantTestnet = mode === 'test'; + const networks = (await api.listNetworks()) + .filter((n) => n.isTestnet === wantTestnet) + .map((n) => n.name); + if (networks.length === 0) return text(`No ${mode} networks are available right now.`, 400); + + // Named after the client so the merchant sees "ChatGPT" on Developers, + // not one more anonymous sk_ row, and knows which key to revoke. + const key = await api.createSecretKey(approval.token, networks, handoff.clientName); + const props: ConnectionProps = { apiKey: key.rawKey, keyPrefix: key.key_prefix, mode }; + const { redirectTo } = await env.OAUTH_PROVIDER.completeAuthorization({ + request: handoff.authRequest, + userId: approval.email ?? 'unknown', + metadata: { clientName: handoff.clientName, keyId: key.id, keyPrefix: key.key_prefix }, + scope: ['agentaos'], + props, + }); + return Response.redirect(redirectTo, 302); +} diff --git a/packages/mcp-remote/src/env.ts b/packages/mcp-remote/src/env.ts new file mode 100644 index 0000000..697cd48 --- /dev/null +++ b/packages/mcp-remote/src/env.ts @@ -0,0 +1,19 @@ +import type { OAuthHelpers } from '@cloudflare/workers-oauth-provider'; + +export interface Env { + OAUTH_KV: KVNamespace; + OAUTH_PROVIDER: OAuthHelpers; + /** Platform API origin, e.g. https://api.agentaos.ai (paths are added per call). */ + AGENTAOS_API_URL: string; + /** This Worker's public origin; the approve page returns the merchant here. */ + MCP_PUBLIC_URL: string; +} + +export type ConnectionMode = 'test' | 'live'; + +/** Encrypted into every access token by the OAuth provider; the only credential a connection holds. */ +export interface ConnectionProps { + apiKey: string; + keyPrefix: string; + mode: ConnectionMode; +} diff --git a/packages/mcp-remote/src/index.ts b/packages/mcp-remote/src/index.ts new file mode 100644 index 0000000..cef66a0 --- /dev/null +++ b/packages/mcp-remote/src/index.ts @@ -0,0 +1,68 @@ +import { OAuthProvider } from '@cloudflare/workers-oauth-provider'; + +import { AgentaosApi } from './agentaos-api.js'; +import { handleAuthorize, handleCallback } from './authorize.js'; +import type { ConnectionProps, Env } from './env.js'; +import { handleMcp } from './mcp.js'; + +/** Everything that is not the protected /mcp route: the OAuth approval leg and a landing line. */ +const defaultHandler: ExportedHandler = { + async fetch(request, env) { + const url = new URL(request.url); + const api = new AgentaosApi(env.AGENTAOS_API_URL); + if (url.pathname === '/authorize') return handleAuthorize({ request, env, api }); + if (url.pathname === '/callback') return handleCallback({ request, env, api }); + if (url.pathname === '/') { + return new Response(`AgentaOS MCP. Add ${env.MCP_PUBLIC_URL}/mcp as a connector.`, { + headers: { 'content-type': 'text/plain; charset=utf-8' }, + }); + } + return new Response('Not found', { status: 404 }); + }, +}; + +/** + * Reached only with a valid access token; the provider decrypts the grant's + * props into ctx.props. Its handler type leaves props `unknown`, hence the cast. + */ +const apiHandler: ExportedHandler & Required, 'fetch'>> = { + fetch(request, env, ctx) { + return handleMcp(request, env, ctx.props as ConnectionProps); + }, +}; + +/** + * Built from the request's env rather than at module load: the issuer and the + * resource URL must match where the Worker is actually reached (local + * `wrangler dev` runs on localhost:8788, production on mcp.agentaos.ai), and + * the MCP client refuses tokens whose audience does not match. + */ +function buildProvider(publicUrl: string): OAuthProvider { + return new OAuthProvider({ + apiRoute: '/mcp', + apiHandler, + defaultHandler, + authorizeEndpoint: '/authorize', + tokenEndpoint: '/token', + clientRegistrationEndpoint: '/register', + clientIdMetadataDocumentEnabled: true, + scopesSupported: ['agentaos'], + resourceMetadata: { + resource: `${publicUrl}/mcp`, + authorization_servers: [publicUrl], + scopes_supported: ['agentaos'], + resource_name: 'AgentaOS', + }, + }); +} + +let cached: { publicUrl: string; provider: OAuthProvider } | undefined; + +export default { + fetch(request, env, ctx) { + if (!cached || cached.publicUrl !== env.MCP_PUBLIC_URL) { + cached = { publicUrl: env.MCP_PUBLIC_URL, provider: buildProvider(env.MCP_PUBLIC_URL) }; + } + return cached.provider.fetch(request, env, ctx); + }, +} satisfies ExportedHandler; diff --git a/packages/mcp-remote/src/mcp.ts b/packages/mcp-remote/src/mcp.ts new file mode 100644 index 0000000..3e2921e --- /dev/null +++ b/packages/mcp-remote/src/mcp.ts @@ -0,0 +1,23 @@ +import { AgentaOS } from '@agentaos/pay'; +import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; +import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js'; +import { registerPayTools } from 'agentaos/mcp'; + +import type { ConnectionProps, Env } from './env.js'; + +/** + * One stateless MCP server per request, with the seven merchant tools bound + * to the key minted for this connection. + */ +export async function handleMcp( + request: Request, + env: Env, + props: ConnectionProps, +): Promise { + const server = new McpServer({ name: 'agentaos', version: '0.1.0' }); + registerPayTools(server, () => new AgentaOS(props.apiKey, { baseUrl: env.AGENTAOS_API_URL })); + + const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: undefined }); + await server.connect(transport); + return transport.handleRequest(request); +} diff --git a/packages/mcp-remote/tsconfig.json b/packages/mcp-remote/tsconfig.json new file mode 100644 index 0000000..cfa0a9c --- /dev/null +++ b/packages/mcp-remote/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "noEmit": true, + "declaration": false, + "declarationMap": false, + "sourceMap": false, + "lib": ["ES2022", "DOM"], + "types": ["@cloudflare/workers-types"] + }, + "include": ["src/**/*"] +} diff --git a/packages/mcp-remote/vitest.config.ts b/packages/mcp-remote/vitest.config.ts new file mode 100644 index 0000000..d061995 --- /dev/null +++ b/packages/mcp-remote/vitest.config.ts @@ -0,0 +1,18 @@ +import { defineConfig } from 'vitest/config'; + +/** + * `@cloudflare/workers-oauth-provider` imports `cloudflare:workers`, which only + * exists inside workerd. The tests run on Node, so that one import is aliased + * to a stub and the provider is inlined so the alias reaches it. + */ +export default defineConfig({ + resolve: { + alias: { + 'cloudflare:workers': new URL('./src/__tests__/cloudflare-workers.stub.ts', import.meta.url) + .pathname, + }, + }, + test: { + server: { deps: { inline: ['@cloudflare/workers-oauth-provider'] } }, + }, +}); diff --git a/packages/mcp-remote/wrangler.jsonc b/packages/mcp-remote/wrangler.jsonc new file mode 100644 index 0000000..0ea6ad7 --- /dev/null +++ b/packages/mcp-remote/wrangler.jsonc @@ -0,0 +1,14 @@ +{ + "$schema": "node_modules/wrangler/config-schema.json", + "name": "agentaos-mcp", + "main": "src/index.ts", + "compatibility_date": "2026-08-01", + "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"], + "kv_namespaces": [{ "binding": "OAUTH_KV", "id": "REPLACE_WITH_KV_ID" }], + "vars": { + "AGENTAOS_API_URL": "https://api.agentaos.ai", + "MCP_PUBLIC_URL": "https://mcp.agentaos.ai" + }, + "routes": [{ "pattern": "mcp.agentaos.ai", "custom_domain": true }], + "observability": { "enabled": true } +} diff --git a/packages/wallet/package.json b/packages/wallet/package.json index 39f1de6..315390e 100644 --- a/packages/wallet/package.json +++ b/packages/wallet/package.json @@ -17,6 +17,12 @@ "agentaos": "./dist/index.js", "agenta": "./dist/index.js" }, + "exports": { + "./mcp": { + "types": "./dist/mcp/tools/index.d.ts", + "default": "./dist/mcp/tools/index.js" + } + }, "files": ["dist", "!dist/__tests__"], "engines": { "node": ">=20.0.0" diff --git a/packages/wallet/src/__tests__/pay-utils.test.ts b/packages/wallet/src/__tests__/pay-utils.test.ts new file mode 100644 index 0000000..926704e --- /dev/null +++ b/packages/wallet/src/__tests__/pay-utils.test.ts @@ -0,0 +1,17 @@ +import { describe, expect, it } from 'vitest'; +import { formatPayError } from '../mcp/tools/pay-utils.js'; + +describe('formatPayError', () => { + it('tells the merchant what to do when the API refuses the key', () => { + const out = formatPayError(new Error('Invalid API key'), 'Failed to list customers'); + expect(out.isError).toBe(true); + expect(out.content[0]?.text).toBe( + 'Failed to list customers: Invalid API key. The key may have been revoked in AgentaOS. Create a new key, or reconnect the connector.', + ); + }); + + it('passes every other error through unchanged', () => { + const out = formatPayError(new Error('Network down'), 'Checkout creation failed'); + expect(out.content[0]?.text).toBe('Checkout creation failed: Network down'); + }); +}); diff --git a/packages/wallet/src/cli/commands/onboarding.command.ts b/packages/wallet/src/cli/commands/onboarding.command.ts index 6ddde0e..5748fac 100644 --- a/packages/wallet/src/cli/commands/onboarding.command.ts +++ b/packages/wallet/src/cli/commands/onboarding.command.ts @@ -116,7 +116,9 @@ const auditRequestCommand = new Command('request') requested: true, productUrl, label: 'Being written', - writtenBy: 'a person, usually within 24 to 48 hours', + // No turnaround promise: a date we miss costs more than a date we + // never gave (same rule as the app, 2026-09-09). + writtenBy: 'a person', }, }); } catch (error: unknown) { diff --git a/packages/wallet/src/mcp/index.ts b/packages/wallet/src/mcp/index.ts index b68057e..c7ed0a3 100644 --- a/packages/wallet/src/mcp/index.ts +++ b/packages/wallet/src/mcp/index.ts @@ -1,13 +1,8 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; -import { registerPayCancelSubscription } from './tools/pay-cancel-subscription.js'; -import { registerPayCreateCheckout } from './tools/pay-create-checkout.js'; -import { registerPayGetCheckout } from './tools/pay-get-checkout.js'; -import { registerPayListCheckouts } from './tools/pay-list-checkouts.js'; -import { registerPayListCustomers } from './tools/pay-list-customers.js'; -import { registerPayListSubscriptions } from './tools/pay-list-subscriptions.js'; -import { registerPaySendReceipt } from './tools/pay-send-receipt.js'; +import { registerPayTools } from './tools/index.js'; +import { createPayClient } from './tools/pay-utils.js'; /** * The AgentaOS MCP server, over stdio. @@ -23,13 +18,7 @@ export async function runMcp() { version: '0.1.0', }); - registerPayCreateCheckout(server); - registerPayGetCheckout(server); - registerPayListCheckouts(server); - registerPayListSubscriptions(server); - registerPayCancelSubscription(server); - registerPayListCustomers(server); - registerPaySendReceipt(server); + registerPayTools(server, createPayClient); const transport = new StdioServerTransport(); await server.connect(transport); diff --git a/packages/wallet/src/mcp/tools/index.ts b/packages/wallet/src/mcp/tools/index.ts new file mode 100644 index 0000000..ccd76cf --- /dev/null +++ b/packages/wallet/src/mcp/tools/index.ts @@ -0,0 +1,30 @@ +import type { AgentaOS } from '@agentaos/pay'; +import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; + +import { registerPayCancelSubscription } from './pay-cancel-subscription.js'; +import { registerPayCreateCheckout } from './pay-create-checkout.js'; +import { registerPayGetCheckout } from './pay-get-checkout.js'; +import { registerPayListCheckouts } from './pay-list-checkouts.js'; +import { registerPayListCustomers } from './pay-list-customers.js'; +import { registerPayListSubscriptions } from './pay-list-subscriptions.js'; +import { registerPaySendReceipt } from './pay-send-receipt.js'; + +export { formatPayError } from './pay-utils.js'; + +/** Builds the Pay SDK client a tool call runs against. Called per tool invocation. */ +export type PayClientFactory = () => AgentaOS; + +/** + * Register the seven merchant tools on any McpServer. The stdio CLI server + * passes the env-based factory; the remote Worker passes one bound to the + * key minted for that connection. + */ +export function registerPayTools(server: McpServer, getClient: PayClientFactory): void { + registerPayCreateCheckout(server, getClient); + registerPayGetCheckout(server, getClient); + registerPayListCheckouts(server, getClient); + registerPayListSubscriptions(server, getClient); + registerPayCancelSubscription(server, getClient); + registerPayListCustomers(server, getClient); + registerPaySendReceipt(server, getClient); +} diff --git a/packages/wallet/src/mcp/tools/pay-cancel-subscription.ts b/packages/wallet/src/mcp/tools/pay-cancel-subscription.ts index d4dff88..e519c5d 100644 --- a/packages/wallet/src/mcp/tools/pay-cancel-subscription.ts +++ b/packages/wallet/src/mcp/tools/pay-cancel-subscription.ts @@ -1,8 +1,9 @@ +import type { AgentaOS } from '@agentaos/pay'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; -import { createPayClient, formatPayError } from './pay-utils.js'; +import { formatPayError } from './pay-utils.js'; -export function registerPayCancelSubscription(server: McpServer) { +export function registerPayCancelSubscription(server: McpServer, getClient: () => AgentaOS) { server.registerTool( 'agenta_pay_cancel_subscription', { @@ -18,7 +19,7 @@ export function registerPayCancelSubscription(server: McpServer) { }, async ({ subscriptionId, atPeriodEnd }) => { try { - const client = createPayClient(); + const client = getClient(); const result = await client.subscriptions.cancel(subscriptionId, { atPeriodEnd: atPeriodEnd ?? true, }); diff --git a/packages/wallet/src/mcp/tools/pay-create-checkout.ts b/packages/wallet/src/mcp/tools/pay-create-checkout.ts index d7b6521..7eb0a64 100644 --- a/packages/wallet/src/mcp/tools/pay-create-checkout.ts +++ b/packages/wallet/src/mcp/tools/pay-create-checkout.ts @@ -1,8 +1,9 @@ +import type { AgentaOS } from '@agentaos/pay'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; -import { createPayClient, formatPayError } from './pay-utils.js'; +import { formatPayError } from './pay-utils.js'; -export function registerPayCreateCheckout(server: McpServer) { +export function registerPayCreateCheckout(server: McpServer, getClient: () => AgentaOS) { server.registerTool( 'agenta_pay_create_checkout', { @@ -33,7 +34,7 @@ export function registerPayCreateCheckout(server: McpServer) { }, async ({ amount, currency, description, buyerEmail, webhookUrl, successUrl, expiresIn }) => { try { - const client = createPayClient(); + const client = getClient(); const checkout = await client.checkouts.create({ amount, currency, diff --git a/packages/wallet/src/mcp/tools/pay-get-checkout.ts b/packages/wallet/src/mcp/tools/pay-get-checkout.ts index 29f6e83..b34c6a6 100644 --- a/packages/wallet/src/mcp/tools/pay-get-checkout.ts +++ b/packages/wallet/src/mcp/tools/pay-get-checkout.ts @@ -1,8 +1,9 @@ +import type { AgentaOS } from '@agentaos/pay'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; -import { createPayClient, formatPayError } from './pay-utils.js'; +import { formatPayError } from './pay-utils.js'; -export function registerPayGetCheckout(server: McpServer) { +export function registerPayGetCheckout(server: McpServer, getClient: () => AgentaOS) { server.registerTool( 'agenta_pay_get_checkout', { @@ -14,7 +15,7 @@ export function registerPayGetCheckout(server: McpServer) { }, async ({ sessionId }) => { try { - const client = createPayClient(); + const client = getClient(); const checkout = await client.checkouts.retrieve(sessionId); // amountOverride is for link-based checkouts; standalone checkouts use the session amount diff --git a/packages/wallet/src/mcp/tools/pay-list-checkouts.ts b/packages/wallet/src/mcp/tools/pay-list-checkouts.ts index b272b71..ff102a4 100644 --- a/packages/wallet/src/mcp/tools/pay-list-checkouts.ts +++ b/packages/wallet/src/mcp/tools/pay-list-checkouts.ts @@ -1,8 +1,9 @@ +import type { AgentaOS } from '@agentaos/pay'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; -import { createPayClient, formatPayError } from './pay-utils.js'; +import { formatPayError } from './pay-utils.js'; -export function registerPayListCheckouts(server: McpServer) { +export function registerPayListCheckouts(server: McpServer, getClient: () => AgentaOS) { server.registerTool( 'agenta_pay_list_checkouts', { @@ -25,7 +26,7 @@ export function registerPayListCheckouts(server: McpServer) { }, async ({ status, limit, offset }) => { try { - const client = createPayClient(); + const client = getClient(); const data = await client.checkouts.list({ status, limit: limit ?? 10, diff --git a/packages/wallet/src/mcp/tools/pay-list-customers.ts b/packages/wallet/src/mcp/tools/pay-list-customers.ts index 86488cb..b6068b6 100644 --- a/packages/wallet/src/mcp/tools/pay-list-customers.ts +++ b/packages/wallet/src/mcp/tools/pay-list-customers.ts @@ -1,8 +1,9 @@ +import type { AgentaOS } from '@agentaos/pay'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; -import { createPayClient, formatPayError } from './pay-utils.js'; +import { formatPayError } from './pay-utils.js'; -export function registerPayListCustomers(server: McpServer) { +export function registerPayListCustomers(server: McpServer, getClient: () => AgentaOS) { server.registerTool( 'agenta_pay_list_customers', { @@ -20,7 +21,7 @@ export function registerPayListCustomers(server: McpServer) { }, async ({ limit, offset }) => { try { - const client = createPayClient(); + const client = getClient(); const data = await client.customers.list({ limit: limit ?? 10, offset: offset ?? 0, diff --git a/packages/wallet/src/mcp/tools/pay-list-subscriptions.ts b/packages/wallet/src/mcp/tools/pay-list-subscriptions.ts index 2e24e7e..653ce39 100644 --- a/packages/wallet/src/mcp/tools/pay-list-subscriptions.ts +++ b/packages/wallet/src/mcp/tools/pay-list-subscriptions.ts @@ -1,6 +1,7 @@ +import type { AgentaOS } from '@agentaos/pay'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; -import { createPayClient, formatPayError } from './pay-utils.js'; +import { formatPayError } from './pay-utils.js'; /** Format integer minor units for display. Platform currencies (EUR/USD) are 2-decimal. */ function formatAmount(minor: number, currency: string): string { @@ -11,7 +12,7 @@ function formatAmount(minor: number, currency: string): string { } } -export function registerPayListSubscriptions(server: McpServer) { +export function registerPayListSubscriptions(server: McpServer, getClient: () => AgentaOS) { server.registerTool( 'agenta_pay_list_subscriptions', { @@ -29,7 +30,7 @@ export function registerPayListSubscriptions(server: McpServer) { }, async ({ limit, offset }) => { try { - const client = createPayClient(); + const client = getClient(); const data = await client.subscriptions.list({ limit: limit ?? 10, offset: offset ?? 0, diff --git a/packages/wallet/src/mcp/tools/pay-send-receipt.ts b/packages/wallet/src/mcp/tools/pay-send-receipt.ts index e259dc3..a97c303 100644 --- a/packages/wallet/src/mcp/tools/pay-send-receipt.ts +++ b/packages/wallet/src/mcp/tools/pay-send-receipt.ts @@ -1,8 +1,9 @@ +import type { AgentaOS } from '@agentaos/pay'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; -import { createPayClient, formatPayError } from './pay-utils.js'; +import { formatPayError } from './pay-utils.js'; -export function registerPaySendReceipt(server: McpServer) { +export function registerPaySendReceipt(server: McpServer, getClient: () => AgentaOS) { server.registerTool( 'agenta_pay_send_receipt', { @@ -14,7 +15,7 @@ export function registerPaySendReceipt(server: McpServer) { }, async ({ invoiceId }) => { try { - const client = createPayClient(); + const client = getClient(); const result = await client.invoices.sendReceipt(invoiceId); return { content: [{ type: 'text' as const, text: `Receipt sent to ${result.sentTo}` }] }; diff --git a/packages/wallet/src/mcp/tools/pay-utils.ts b/packages/wallet/src/mcp/tools/pay-utils.ts index 2514ab8..4313b14 100644 --- a/packages/wallet/src/mcp/tools/pay-utils.ts +++ b/packages/wallet/src/mcp/tools/pay-utils.ts @@ -17,11 +17,20 @@ export function createPayClient(): AgentaOS { return new AgentaOS(apiKey, baseUrl ? { baseUrl } : undefined); } +/** What the merchant can do when the API refuses the key: it was revoked on the + * Developers tab (a connector disconnect) or never valid. Said here, once, so + * every tool answers the same way. */ +const REVOKED_KEY_HINT = + 'The key may have been revoked in AgentaOS. Create a new key, or reconnect the connector.'; + /** Format SDK errors for MCP tool responses. */ export function formatPayError(error: unknown, prefix: string) { const msg = error instanceof Error ? error.message : String(error); + const text = /invalid api key/i.test(msg) + ? `${prefix}: ${msg}. ${REVOKED_KEY_HINT}` + : `${prefix}: ${msg}`; return { - content: [{ type: 'text' as const, text: `${prefix}: ${msg}` }], + content: [{ type: 'text' as const, text }], isError: true, }; } diff --git a/plugins/agentaos/README.md b/plugins/agentaos/README.md index 95f6d77..c9075b3 100644 --- a/plugins/agentaos/README.md +++ b/plugins/agentaos/README.md @@ -55,6 +55,15 @@ agenta login claude mcp list # expect an "agentaos" server, connected ``` +## ChatGPT, Claude.ai and other hosted assistants + +Hosted assistants cannot run `npx`; they connect over HTTPS instead. Add +`https://mcp.agentaos.ai/mcp` as a custom connector (ChatGPT: Settings → +Connectors; Claude.ai: Customize → Connectors → Add custom connector). An +AgentaOS page opens: pick Test or Live and press **Approve**. The assistant then +has the same `agenta_pay_*` tools as this plugin. To disconnect, revoke the key +on app.agentaos.ai → Developers. + ## Docs - Skill reference: `skills/agentaos/SKILL.md` (source of truth: diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bda853f..4bced50 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,7 +31,7 @@ importers: version: 16.2.7 openai: specifier: ^6.22.0 - version: 6.22.0(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(zod@4.3.6) + version: 6.22.0(ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(zod@4.3.6) tsx: specifier: ^4.19.0 version: 4.21.0 @@ -155,6 +155,37 @@ importers: packages/core: {} + packages/mcp-remote: + dependencies: + '@agentaos/pay': + specifier: workspace:^ + version: link:../pay + '@cloudflare/workers-oauth-provider': + specifier: ^0.10.3 + version: 0.10.3 + '@modelcontextprotocol/sdk': + specifier: ^1.26.0 + version: 1.26.0(@cfworker/json-schema@4.1.1)(zod@3.25.76) + agentaos: + specifier: workspace:^ + version: link:../wallet + zod: + specifier: ^3.24.0 + version: 3.25.76 + devDependencies: + '@cloudflare/workers-types': + specifier: ^5.20260908.1 + version: 5.20260908.1 + typescript: + specifier: ^5.6.0 + version: 5.9.3 + vitest: + specifier: ^2.0.0 + version: 2.1.9(@types/node@20.19.32) + wrangler: + specifier: ^4.130.0 + version: 4.130.0(@cloudflare/workers-types@5.20260908.1)(bufferutil@4.1.0)(utf-8-validate@5.0.10) + packages/mpc-wasm: {} packages/pay: @@ -399,6 +430,62 @@ packages: '@changesets/write@0.4.0': resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} + '@cloudflare/kv-asset-handler@0.5.0': + resolution: {integrity: sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==} + engines: {node: '>=22.0.0'} + + '@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/workerd-darwin-64@1.20260908.1': + resolution: {integrity: sha512-t3juyCXFn12OklBL0S7UC98py3nLEmuioBOUOazeyeVsLUu8fv+pfJrR+XzwSH2Uh6rCXZNogRh+LtV0YpzMcQ==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + + '@cloudflare/workerd-darwin-arm64@1.20260908.1': + resolution: {integrity: sha512-I1nwA4qm/fUNSKhPSO76YA6JAhcA0KU63yFcYHN6AiDowGbDyfjDPH9KCVopT5rI1LY4GfbdAi5b9gODqZsAkQ==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + + '@cloudflare/workerd-linux-64@1.20260908.1': + resolution: {integrity: sha512-s/h5uSW1UC6dGeVKSqrPLpTu+vo0fKJZCNEokW1Ol1qcCB2oN6WCRHhoyzo4Y69oONAXRgLfLBYaHWe7z51Vnw==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + + '@cloudflare/workerd-linux-arm64@1.20260908.1': + resolution: {integrity: sha512-PP/nUKl0R6colwfocggL8dctO/dFMqMft12unzFUkoAJr0aXQeT+ia0JuNmOUWXe6EfvyCSmAbijEsTKQ5t/ew==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + + '@cloudflare/workerd-windows-64@1.20260908.1': + resolution: {integrity: sha512-jkaS5EKKTvzAdIlbMfOYrHoTucWVRwYBwIig+xRsjXQv5BXTLA2Llg+iM8djlKtk0CjkztZhXmuxuqoqWKZmFw==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + + '@cloudflare/workers-oauth-provider@0.10.3': + resolution: {integrity: sha512-25ufMONJir9PllqVpK4GwOOoSFgpYm3+bM6NBedj7ufMCIfNf5jk4OI0LPuTJBaJgLl2lGCLqFqEPJXcSuPopQ==} + + '@cloudflare/workers-types@5.20260908.1': + resolution: {integrity: sha512-cILmYEd/YtL+Hlwytc5n+QVV8F+E5doQOtc6QiBtPb51kK+5fkk909db+G8dxeUsMd2ytJgdpAt/lyciUEobcw==} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@emnapi/runtime@1.11.3': + resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==} + '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} @@ -411,6 +498,12 @@ packages: 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.21.5': resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} @@ -423,6 +516,12 @@ packages: 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.21.5': resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} @@ -435,6 +534,12 @@ packages: 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.21.5': resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} @@ -447,6 +552,12 @@ packages: 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.21.5': resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} @@ -459,6 +570,12 @@ packages: 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.21.5': resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} @@ -471,6 +588,12 @@ packages: 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.21.5': resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} @@ -483,6 +606,12 @@ packages: 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.21.5': resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} @@ -495,6 +624,12 @@ packages: 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.21.5': resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} @@ -507,6 +642,12 @@ packages: 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.21.5': resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} @@ -519,6 +660,12 @@ packages: 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.21.5': resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} @@ -531,6 +678,12 @@ packages: 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.21.5': resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} @@ -543,6 +696,12 @@ packages: 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.21.5': resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} @@ -555,6 +714,12 @@ packages: 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.21.5': resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} @@ -567,6 +732,12 @@ packages: 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.21.5': resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} @@ -579,6 +750,12 @@ packages: 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.21.5': resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} @@ -591,6 +768,12 @@ packages: 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.21.5': resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} @@ -603,12 +786,24 @@ packages: 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.3': resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} 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.21.5': resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} @@ -621,12 +816,24 @@ packages: 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.3': resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} 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.21.5': resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} @@ -639,12 +846,24 @@ packages: 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.3': resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} 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.21.5': resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} @@ -657,6 +876,12 @@ packages: 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.21.5': resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} @@ -669,6 +894,12 @@ packages: 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.21.5': resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} @@ -681,6 +912,12 @@ packages: 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.21.5': resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} @@ -693,6 +930,12 @@ packages: 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] + '@google/generative-ai@0.24.1': resolution: {integrity: sha512-MqO+MLfM6kjxcKoy0p1wRzG3b4ZZXtPI+z2IE26UogS2Cm/XHO+7gGRBh6gcJsOiIVoH93UwKvW4HdgiOZCy9Q==} engines: {node: '>=18.0.0'} @@ -703,89 +946,235 @@ packages: peerDependencies: hono: ^4 + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + '@img/sharp-darwin-arm64@0.33.5': resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [darwin] + '@img/sharp-darwin-arm64@0.35.2': + resolution: {integrity: sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [darwin] + '@img/sharp-darwin-x64@0.33.5': resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] + '@img/sharp-darwin-x64@0.35.2': + resolution: {integrity: sha512-BaktuGPCeHJMARpodR8jK4uKiZrPAy9WrfQW0sdI37clracq8Bp01AYS3SZgi5FS/y5twa9t4+LIuuxQjqRrWw==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-freebsd-wasm32@0.35.2': + resolution: {integrity: sha512-YoAxdnd8hPUkvLHd3bWY+YA8nw3xM/RyRopYucNsWHVSan8NLVM3X2volsfoRDcXdUJPg6tXahSd7HXPK7lRnw==} + engines: {node: '>=20.9.0'} + os: [freebsd] + '@img/sharp-libvips-darwin-arm64@1.0.4': resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} cpu: [arm64] os: [darwin] + '@img/sharp-libvips-darwin-arm64@1.3.1': + resolution: {integrity: sha512-4V/M3roRMTYjiwZY9IOVQOE8OyeCxFAkYmyZDrZl51uOKjibm3oeEJ4WAmLxutAfzFbC9jqUiPs2gbnGflH+7g==} + cpu: [arm64] + os: [darwin] + '@img/sharp-libvips-darwin-x64@1.0.4': resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} cpu: [x64] os: [darwin] + '@img/sharp-libvips-darwin-x64@1.3.1': + resolution: {integrity: sha512-c0/DxItpJv2+dGhgycJBBgotdqruGYDvA79drdh0MD1dFpy7JzJ/PlXwi1H4rFf0eTy8tgbI91aHDnZIceY3jQ==} + cpu: [x64] + os: [darwin] + '@img/sharp-libvips-linux-arm64@1.0.4': resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} cpu: [arm64] os: [linux] + '@img/sharp-libvips-linux-arm64@1.3.1': + resolution: {integrity: sha512-JznefmcK9j1JKPz8AkQDh89kjojubyfOasWBPKfzMIhPwsgDy9evpE/naJTXXXmghS1iFwR8u/kTwh/I2/+GCw==} + cpu: [arm64] + os: [linux] + '@img/sharp-libvips-linux-arm@1.0.5': resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} cpu: [arm] os: [linux] + '@img/sharp-libvips-linux-arm@1.3.1': + resolution: {integrity: sha512-aGGy9aWzXgHBG7HNyQPWorZthlp7+x6fDRoPAQbGO3ThcttuTyKIx3NuSHb6zb4gBNq6/yNn9f1cy9nFKS/Vmg==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-ppc64@1.3.1': + resolution: {integrity: sha512-1EkwGNCZk6iWNCMWqrvdJ+r1j0PT1zIz60CNPhYnJlK/zyeWqlsPZIe+ocBVqPF8k/Ssee/NCk+tE9Ryrko6ng==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-riscv64@1.3.1': + resolution: {integrity: sha512-Ilays+w2bXdnxzxtQdmXR62u8o8GYa3eL4+Gr+1KiE4xperMZUslRaVPJwwPkzlHEjGfXAfRVAa/7CYCtSqsBw==} + cpu: [riscv64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.3.1': + resolution: {integrity: sha512-VfBwVHQTbRoj4XlpA/KLZ7ltgMpz+4WSejFzQ+GnoImjo1PtEJ59QB2qR1xQEeRPYIkNrPIm2L4cICMvz4C2ew==} + cpu: [s390x] + os: [linux] + '@img/sharp-libvips-linux-x64@1.0.4': resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} cpu: [x64] os: [linux] + '@img/sharp-libvips-linux-x64@1.3.1': + resolution: {integrity: sha512-+c8ukgwU62DS54nCAjw7keOfHUkmr0B5QHEdcOqRnodF/MNXJbVI8Eopoj4B/0H8Asr65I+A4Amrn7a85/md6A==} + cpu: [x64] + os: [linux] + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} cpu: [arm64] os: [linux] + '@img/sharp-libvips-linuxmusl-arm64@1.3.1': + resolution: {integrity: sha512-qlKb/pwbkAi1WMsJrYHk7CuDrd12s27U2QnRhFYUoJNrRCmkosMTttuRFat/DDB3IlDm5qE1TJgZ4JDnHX8Ldw==} + cpu: [arm64] + os: [linux] + '@img/sharp-libvips-linuxmusl-x64@1.0.4': resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} cpu: [x64] os: [linux] + '@img/sharp-libvips-linuxmusl-x64@1.3.1': + resolution: {integrity: sha512-yO21HwoUVLN8Qa+/SBjQLMYwBWAVJjeGPNe+hc0OUeMeifEtJqu5a1c4HayE1nNpDih9y3/KkoltfkDodmKAlg==} + cpu: [x64] + os: [linux] + '@img/sharp-linux-arm64@0.33.5': resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + '@img/sharp-linux-arm64@0.35.2': + resolution: {integrity: sha512-af12Pnd0ZGu2HfP8NayB0kk6eC/lrfbQE6HlR4jD+34wdJ1Vw9TF6TMn6ZvffT+WgqVsl0hRbmNvz2u/23VmwA==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + '@img/sharp-linux-arm@0.33.5': resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] + '@img/sharp-linux-arm@0.35.2': + resolution: {integrity: sha512-SE4kzF2mepn6z+6E7L6lsV8FzuLL6IPQdyX8ZiwROAG/G8td+hP/m7FsFPwidtrF19gvajuC9l6TxAVcsA4S7A==} + engines: {node: '>=20.9.0'} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-ppc64@0.35.2': + resolution: {integrity: sha512-hYSBm7zcNtDCozCxQHYZJiu63b/bXsgRZuOxCIBZsStMM9Vap47iFHdbX4kCvQsblPB/k+clhELpdQJHQLSHvg==} + engines: {node: '>=20.9.0'} + cpu: [ppc64] + os: [linux] + + '@img/sharp-linux-riscv64@0.35.2': + resolution: {integrity: sha512-qQt0Kc13+Hoan/Awq/qMSQw3L+RI1NCRPgD5cUJ/1WSSmIoysLOc72jlRM3E0OHN9Yr313jgeQ2T+zW+F03QFA==} + engines: {node: '>=20.9.0'} + cpu: [riscv64] + os: [linux] + + '@img/sharp-linux-s390x@0.35.2': + resolution: {integrity: sha512-E4fLLfRPzDLlEeDaTzI98OFLcv++WL5ChLLMwPoVd0CIoZQqupBSNbOisPL5am9XsbQ9T84+iiMpUvbFtkunbA==} + engines: {node: '>=20.9.0'} + cpu: [s390x] + os: [linux] + '@img/sharp-linux-x64@0.33.5': resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + '@img/sharp-linux-x64@0.35.2': + resolution: {integrity: sha512-gi0zFJJRLswfCZmHtJdikXPOc5u7qamSOS3NHedLqLd4W8Q0NqjdBr6TTRIgsfFjqfTsHFgdfvJ9LwqSgcHiAA==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + '@img/sharp-linuxmusl-arm64@0.33.5': resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + '@img/sharp-linuxmusl-arm64@0.35.2': + resolution: {integrity: sha512-siWbOW1u6HFnFLrp0waKyW7VEf7jYvcDWdrXEFa8AkdAQgEvuu5Fz8/Y70w9EeqAdwDtfU012BhEHHaDqvQNzg==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + '@img/sharp-linuxmusl-x64@0.33.5': resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + '@img/sharp-linuxmusl-x64@0.35.2': + resolution: {integrity: sha512-YBqMMcjDi4QGYiSn4vNOYBhmlC4z5AXqkOUUqI2e0AFA4urNv4ESgOgwNl3K+4etQhha0twXlzeF20bbULm9Yg==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.35.2': + resolution: {integrity: sha512-Mrv4JQNYVQ94xH+jzZ9r+gowleN8mv2FTgKT+PI6bx5C0G8TdNYndu161pg2i7uoBwxy2ImPMHrJOM2LZef7Bw==} + engines: {node: '>=20.9.0'} + + '@img/sharp-webcontainers-wasm32@0.35.2': + resolution: {integrity: sha512-QNV27pxs9wpApEiCfvHM1RDoP1w1+2KrUWWDPEhEwg+latvOrfuhWrHWZKwdSFwU6jh3myjw/yOCRsUIuOft3g==} + engines: {node: '>=20.9.0'} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.35.2': + resolution: {integrity: sha512-BiVRYc/t6/Vl3e1hBx0hugG4oN9Pydf4fgMSpxTQJmwGUg/YoXTWHiFeRymHfCZzifxu4F4rpk/I67D0LQ20wQ==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.35.2': + resolution: {integrity: sha512-YYEhx9PImCC7T0tI8JDMi4DB9LwLCXCU5OWNYEXAxh5Q1ShKkyC6byxzoBJ3gEFDnH2lQckWuDe70G7mB2XJog==} + engines: {node: ^20.9.0} + cpu: [ia32] + os: [win32] + '@img/sharp-win32-x64@0.33.5': resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [win32] + '@img/sharp-win32-x64@0.35.2': + resolution: {integrity: sha512-imoOyBcoM/iiUr4J6VPpCNjPnjvP/Gks95898yB8YqoGGYmHYbOyCuNv9FMhFgtaiHFGbHW8bxKqRV6VjtXThQ==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [win32] + '@inquirer/external-editor@1.0.3': resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} engines: {node: '>=18'} @@ -795,9 +1184,16 @@ packages: '@types/node': optional: true + '@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.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@langchain/core@0.3.80': resolution: {integrity: sha512-vcJDV2vk1AlCwSh3aBm/urQ1ZrlXFFBocv11bz/NBUfLWD5/UDNMzwPdaAd2dKvNmTWa9FM2lirLU3+JCf4cRA==} engines: {node: '>=18'} @@ -864,6 +1260,15 @@ packages: resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} + '@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==} + '@rollup/rollup-android-arm-eabi@4.57.1': resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} cpu: [arm] @@ -998,6 +1403,13 @@ packages: '@scure/bip39@1.6.0': resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==} + '@sindresorhus/is@7.2.0': + resolution: {integrity: sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==} + engines: {node: '>=18'} + + '@speed-highlight/core@1.2.24': + resolution: {integrity: sha512-qeW2e1l78afw8VhRPfPQ1Gjj+KU5XFQ/OFV5ti6eTa9bruO7mJyZtA4vw0ofqmA3tKCkROE9xLk3VZoeRc98nw==} + '@types/body-parser@1.19.6': resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} @@ -1164,6 +1576,9 @@ packages: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} + blake3-wasm@2.1.5: + resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} + body-parser@1.20.4: resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -1279,6 +1694,10 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + cors@2.8.5: resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} engines: {node: '>= 0.10'} @@ -1331,6 +1750,10 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + diff-match-patch@1.0.5: resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} @@ -1364,6 +1787,9 @@ packages: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} engines: {node: '>=18'} + 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'} @@ -1389,6 +1815,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.28.1: + resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + engines: {node: '>=18'} + hasBin: true + escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -1663,6 +2094,10 @@ packages: jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + langsmith@0.3.87: resolution: {integrity: sha512-XXR1+9INH8YX96FKWc5tie0QixWz6tOqAsAKfcJyPkE0xPep+NDz0IQLR32q4bn10QK3LqD2HN6T3n6z1YLW7Q==} peerDependencies: @@ -1770,6 +2205,10 @@ packages: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} + miniflare@5.20260908.0-alpha: + resolution: {integrity: sha512-BHIknb0u6vLIvb+R8PsUAzgoWWk3OlW85DrV2SG0EydfSpIba28YT0rH6xZThjnSwDxzNuW3FDRNSWvbiI/DVw==} + engines: {node: '>=22.0.0'} + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -1926,6 +2365,9 @@ packages: path-to-regexp@0.1.12: resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + path-to-regexp@8.3.0: resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} @@ -1936,6 +2378,9 @@ packages: pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pathval@2.0.1: resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} engines: {node: '>= 14.16'} @@ -2055,6 +2500,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + send@0.19.2: resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} engines: {node: '>= 0.8.0'} @@ -2074,6 +2524,10 @@ packages: setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + sharp@0.35.2: + resolution: {integrity: sha512-FVtFjtBCMiJS6yb5CX7Sop45WFMpeGw6oRKuJnXYgf/f1ms/D7LE/ZUSNxnW7rZ/dbslQWYkoqFHGPaDBtaK4w==} + engines: {node: '>=20.9.0'} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -2164,6 +2618,10 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} + supports-color@10.2.2: + resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} + engines: {node: '>=18'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -2213,6 +2671,9 @@ packages: ts-algebra@2.0.0: resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsx@4.21.0: resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} engines: {node: '>=18.0.0'} @@ -2268,6 +2729,13 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici@7.29.0: + resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} + engines: {node: '>=20.18.1'} + + unenv@2.0.0-rc.24: + resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -2382,6 +2850,21 @@ packages: engines: {node: '>=8'} hasBin: true + workerd@1.20260908.1: + resolution: {integrity: sha512-rYhpW6NWHD++p34ej+VXWzi5Pdnmd7ncdbB/ux4s+i3mf7IeOpW3O4roqClQ+Z8ernvyMCknBLCb76z1rA+a7Q==} + engines: {node: '>=16'} + hasBin: true + + wrangler@4.130.0: + resolution: {integrity: sha512-fzNjnTzyZl31PGJOFXbiLeZqEIToQ9KOzkkvGdQz4wlB+BoHnl3BRwCR5xg8AqYyzVunvvMHlMzvlbThQ7rrAA==} + engines: {node: '>=22.0.0'} + hasBin: true + peerDependencies: + '@cloudflare/workers-types': ^5.20260908.1 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} @@ -2401,8 +2884,8 @@ packages: utf-8-validate: optional: true - ws@8.19.0: - resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} + ws@8.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -2418,6 +2901,12 @@ packages: engines: {node: '>= 14.6'} hasBin: true + 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.1: resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} peerDependencies: @@ -2684,218 +3173,438 @@ snapshots: human-id: 4.1.3 prettier: 2.8.8 + '@cloudflare/kv-asset-handler@0.5.0': {} + + '@cloudflare/unenv-preset@2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260908.1)': + dependencies: + unenv: 2.0.0-rc.24 + optionalDependencies: + workerd: 1.20260908.1 + + '@cloudflare/workerd-darwin-64@1.20260908.1': + optional: true + + '@cloudflare/workerd-darwin-arm64@1.20260908.1': + optional: true + + '@cloudflare/workerd-linux-64@1.20260908.1': + optional: true + + '@cloudflare/workerd-linux-arm64@1.20260908.1': + optional: true + + '@cloudflare/workerd-windows-64@1.20260908.1': + optional: true + + '@cloudflare/workers-oauth-provider@0.10.3': {} + + '@cloudflare/workers-types@5.20260908.1': {} + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@emnapi/runtime@1.11.3': + dependencies: + tslib: 2.8.1 + optional: true + '@esbuild/aix-ppc64@0.21.5': optional: true '@esbuild/aix-ppc64@0.27.3': optional: true + '@esbuild/aix-ppc64@0.28.1': + optional: true + '@esbuild/android-arm64@0.21.5': optional: true '@esbuild/android-arm64@0.27.3': optional: true + '@esbuild/android-arm64@0.28.1': + optional: true + '@esbuild/android-arm@0.21.5': optional: true '@esbuild/android-arm@0.27.3': optional: true + '@esbuild/android-arm@0.28.1': + optional: true + '@esbuild/android-x64@0.21.5': optional: true '@esbuild/android-x64@0.27.3': optional: true + '@esbuild/android-x64@0.28.1': + optional: true + '@esbuild/darwin-arm64@0.21.5': optional: true '@esbuild/darwin-arm64@0.27.3': optional: true + '@esbuild/darwin-arm64@0.28.1': + optional: true + '@esbuild/darwin-x64@0.21.5': optional: true '@esbuild/darwin-x64@0.27.3': optional: true + '@esbuild/darwin-x64@0.28.1': + optional: true + '@esbuild/freebsd-arm64@0.21.5': optional: true '@esbuild/freebsd-arm64@0.27.3': optional: true + '@esbuild/freebsd-arm64@0.28.1': + optional: true + '@esbuild/freebsd-x64@0.21.5': optional: true '@esbuild/freebsd-x64@0.27.3': optional: true + '@esbuild/freebsd-x64@0.28.1': + optional: true + '@esbuild/linux-arm64@0.21.5': optional: true '@esbuild/linux-arm64@0.27.3': optional: true + '@esbuild/linux-arm64@0.28.1': + optional: true + '@esbuild/linux-arm@0.21.5': optional: true '@esbuild/linux-arm@0.27.3': optional: true + '@esbuild/linux-arm@0.28.1': + optional: true + '@esbuild/linux-ia32@0.21.5': optional: true '@esbuild/linux-ia32@0.27.3': optional: true + '@esbuild/linux-ia32@0.28.1': + optional: true + '@esbuild/linux-loong64@0.21.5': optional: true '@esbuild/linux-loong64@0.27.3': optional: true + '@esbuild/linux-loong64@0.28.1': + optional: true + '@esbuild/linux-mips64el@0.21.5': optional: true '@esbuild/linux-mips64el@0.27.3': optional: true + '@esbuild/linux-mips64el@0.28.1': + optional: true + '@esbuild/linux-ppc64@0.21.5': optional: true '@esbuild/linux-ppc64@0.27.3': optional: true + '@esbuild/linux-ppc64@0.28.1': + optional: true + '@esbuild/linux-riscv64@0.21.5': optional: true '@esbuild/linux-riscv64@0.27.3': optional: true + '@esbuild/linux-riscv64@0.28.1': + optional: true + '@esbuild/linux-s390x@0.21.5': optional: true '@esbuild/linux-s390x@0.27.3': optional: true + '@esbuild/linux-s390x@0.28.1': + optional: true + '@esbuild/linux-x64@0.21.5': optional: true '@esbuild/linux-x64@0.27.3': optional: true + '@esbuild/linux-x64@0.28.1': + optional: true + '@esbuild/netbsd-arm64@0.27.3': optional: true + '@esbuild/netbsd-arm64@0.28.1': + optional: true + '@esbuild/netbsd-x64@0.21.5': optional: true '@esbuild/netbsd-x64@0.27.3': optional: true + '@esbuild/netbsd-x64@0.28.1': + optional: true + '@esbuild/openbsd-arm64@0.27.3': optional: true + '@esbuild/openbsd-arm64@0.28.1': + optional: true + '@esbuild/openbsd-x64@0.21.5': optional: true '@esbuild/openbsd-x64@0.27.3': optional: true + '@esbuild/openbsd-x64@0.28.1': + optional: true + '@esbuild/openharmony-arm64@0.27.3': optional: true + '@esbuild/openharmony-arm64@0.28.1': + optional: true + '@esbuild/sunos-x64@0.21.5': optional: true '@esbuild/sunos-x64@0.27.3': optional: true + '@esbuild/sunos-x64@0.28.1': + optional: true + '@esbuild/win32-arm64@0.21.5': optional: true '@esbuild/win32-arm64@0.27.3': optional: true + '@esbuild/win32-arm64@0.28.1': + optional: true + '@esbuild/win32-ia32@0.21.5': optional: true '@esbuild/win32-ia32@0.27.3': optional: true + '@esbuild/win32-ia32@0.28.1': + optional: true + '@esbuild/win32-x64@0.21.5': optional: true '@esbuild/win32-x64@0.27.3': optional: true + '@esbuild/win32-x64@0.28.1': + optional: true + '@google/generative-ai@0.24.1': {} '@hono/node-server@1.19.9(hono@4.11.9)': dependencies: hono: 4.11.9 + '@img/colour@1.1.0': {} + '@img/sharp-darwin-arm64@0.33.5': optionalDependencies: '@img/sharp-libvips-darwin-arm64': 1.0.4 optional: true + '@img/sharp-darwin-arm64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.3.1 + optional: true + '@img/sharp-darwin-x64@0.33.5': optionalDependencies: '@img/sharp-libvips-darwin-x64': 1.0.4 optional: true + '@img/sharp-darwin-x64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.3.1 + optional: true + + '@img/sharp-freebsd-wasm32@0.35.2': + dependencies: + '@img/sharp-wasm32': 0.35.2 + optional: true + '@img/sharp-libvips-darwin-arm64@1.0.4': optional: true + '@img/sharp-libvips-darwin-arm64@1.3.1': + optional: true + '@img/sharp-libvips-darwin-x64@1.0.4': optional: true + '@img/sharp-libvips-darwin-x64@1.3.1': + optional: true + '@img/sharp-libvips-linux-arm64@1.0.4': optional: true + '@img/sharp-libvips-linux-arm64@1.3.1': + optional: true + '@img/sharp-libvips-linux-arm@1.0.5': optional: true + '@img/sharp-libvips-linux-arm@1.3.1': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.3.1': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.3.1': + optional: true + + '@img/sharp-libvips-linux-s390x@1.3.1': + optional: true + '@img/sharp-libvips-linux-x64@1.0.4': optional: true + '@img/sharp-libvips-linux-x64@1.3.1': + optional: true + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': optional: true + '@img/sharp-libvips-linuxmusl-arm64@1.3.1': + optional: true + '@img/sharp-libvips-linuxmusl-x64@1.0.4': optional: true + '@img/sharp-libvips-linuxmusl-x64@1.3.1': + optional: true + '@img/sharp-linux-arm64@0.33.5': optionalDependencies: '@img/sharp-libvips-linux-arm64': 1.0.4 optional: true + '@img/sharp-linux-arm64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.3.1 + optional: true + '@img/sharp-linux-arm@0.33.5': optionalDependencies: '@img/sharp-libvips-linux-arm': 1.0.5 optional: true + '@img/sharp-linux-arm@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.3.1 + optional: true + + '@img/sharp-linux-ppc64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.3.1 + optional: true + + '@img/sharp-linux-riscv64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.3.1 + optional: true + + '@img/sharp-linux-s390x@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.3.1 + optional: true + '@img/sharp-linux-x64@0.33.5': optionalDependencies: '@img/sharp-libvips-linux-x64': 1.0.4 optional: true + '@img/sharp-linux-x64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.3.1 + optional: true + '@img/sharp-linuxmusl-arm64@0.33.5': optionalDependencies: '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 optional: true + '@img/sharp-linuxmusl-arm64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.3.1 + optional: true + '@img/sharp-linuxmusl-x64@0.33.5': optionalDependencies: '@img/sharp-libvips-linuxmusl-x64': 1.0.4 optional: true + '@img/sharp-linuxmusl-x64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.3.1 + optional: true + + '@img/sharp-wasm32@0.35.2': + dependencies: + '@emnapi/runtime': 1.11.3 + optional: true + + '@img/sharp-webcontainers-wasm32@0.35.2': + dependencies: + '@img/sharp-wasm32': 0.35.2 + optional: true + + '@img/sharp-win32-arm64@0.35.2': + optional: true + + '@img/sharp-win32-ia32@0.35.2': + optional: true + '@img/sharp-win32-x64@0.33.5': optional: true + '@img/sharp-win32-x64@0.35.2': + optional: true + '@inquirer/external-editor@1.0.3(@types/node@20.19.32)': dependencies: chardet: 2.1.1 @@ -2903,8 +3612,15 @@ snapshots: optionalDependencies: '@types/node': 20.19.32 + '@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 + '@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(openai@6.22.0(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@5.0.10))(zod@3.25.76))': dependencies: '@cfworker/json-schema': 4.1.1 @@ -3030,6 +3746,18 @@ snapshots: '@opentelemetry/api@1.9.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': {} + '@rollup/rollup-android-arm-eabi@4.57.1': optional: true @@ -3118,6 +3846,10 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 + '@sindresorhus/is@7.2.0': {} + + '@speed-highlight/core@1.2.24': {} + '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 @@ -3288,6 +4020,8 @@ snapshots: dependencies: is-windows: 1.0.2 + blake3-wasm@2.1.5: {} + body-parser@1.20.4: dependencies: bytes: 3.1.2 @@ -3406,6 +4140,8 @@ snapshots: cookie@0.7.2: {} + cookie@1.1.1: {} + cors@2.8.5: dependencies: object-assign: 4.1.1 @@ -3439,6 +4175,8 @@ snapshots: detect-indent@6.1.0: {} + detect-libc@2.1.2: {} + diff-match-patch@1.0.5: {} dir-glob@3.0.1: @@ -3466,6 +4204,8 @@ snapshots: environment@1.1.0: {} + error-stack-parser-es@1.0.5: {} + es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -3531,6 +4271,35 @@ snapshots: '@esbuild/win32-ia32': 0.27.3 '@esbuild/win32-x64': 0.27.3 + esbuild@0.28.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.1 + '@esbuild/android-arm': 0.28.1 + '@esbuild/android-arm64': 0.28.1 + '@esbuild/android-x64': 0.28.1 + '@esbuild/darwin-arm64': 0.28.1 + '@esbuild/darwin-x64': 0.28.1 + '@esbuild/freebsd-arm64': 0.28.1 + '@esbuild/freebsd-x64': 0.28.1 + '@esbuild/linux-arm': 0.28.1 + '@esbuild/linux-arm64': 0.28.1 + '@esbuild/linux-ia32': 0.28.1 + '@esbuild/linux-loong64': 0.28.1 + '@esbuild/linux-mips64el': 0.28.1 + '@esbuild/linux-ppc64': 0.28.1 + '@esbuild/linux-riscv64': 0.28.1 + '@esbuild/linux-s390x': 0.28.1 + '@esbuild/linux-x64': 0.28.1 + '@esbuild/netbsd-arm64': 0.28.1 + '@esbuild/netbsd-x64': 0.28.1 + '@esbuild/openbsd-arm64': 0.28.1 + '@esbuild/openbsd-x64': 0.28.1 + '@esbuild/openharmony-arm64': 0.28.1 + '@esbuild/sunos-x64': 0.28.1 + '@esbuild/win32-arm64': 0.28.1 + '@esbuild/win32-ia32': 0.28.1 + '@esbuild/win32-x64': 0.28.1 + escape-html@1.0.3: {} esprima@4.0.1: {} @@ -3849,6 +4618,8 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + kleur@4.1.5: {} + langsmith@0.3.87(@opentelemetry/api@1.9.0)(openai@6.22.0(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@5.0.10))(zod@3.25.76)): dependencies: '@types/uuid': 10.0.0 @@ -3944,6 +4715,18 @@ snapshots: mimic-function@5.0.1: {} + miniflare@5.20260908.0-alpha(bufferutil@4.1.0)(utf-8-validate@5.0.10): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + sharp: 0.35.2 + undici: 7.29.0 + workerd: 1.20260908.1 + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + youch: 4.1.0-beta.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + mri@1.2.0: {} ms@2.0.0: {} @@ -3994,9 +4777,9 @@ snapshots: zod: 3.25.76 optional: true - openai@6.22.0(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(zod@4.3.6): + openai@6.22.0(ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(zod@4.3.6): optionalDependencies: - ws: 8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) zod: 4.3.6 ora@8.2.0: @@ -4087,12 +4870,16 @@ snapshots: path-to-regexp@0.1.12: {} + path-to-regexp@6.3.0: {} + path-to-regexp@8.3.0: {} path-type@4.0.0: {} pathe@1.1.2: {} + pathe@2.0.3: {} + pathval@2.0.1: {} picocolors@1.1.1: {} @@ -4223,6 +5010,8 @@ snapshots: semver@7.7.4: {} + semver@7.8.5: {} + send@0.19.2: dependencies: debug: 2.6.9 @@ -4277,6 +5066,38 @@ snapshots: setprototypeof@1.2.0: {} + sharp@0.35.2: + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.8.5 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.35.2 + '@img/sharp-darwin-x64': 0.35.2 + '@img/sharp-freebsd-wasm32': 0.35.2 + '@img/sharp-libvips-darwin-arm64': 1.3.1 + '@img/sharp-libvips-darwin-x64': 1.3.1 + '@img/sharp-libvips-linux-arm': 1.3.1 + '@img/sharp-libvips-linux-arm64': 1.3.1 + '@img/sharp-libvips-linux-ppc64': 1.3.1 + '@img/sharp-libvips-linux-riscv64': 1.3.1 + '@img/sharp-libvips-linux-s390x': 1.3.1 + '@img/sharp-libvips-linux-x64': 1.3.1 + '@img/sharp-libvips-linuxmusl-arm64': 1.3.1 + '@img/sharp-libvips-linuxmusl-x64': 1.3.1 + '@img/sharp-linux-arm': 0.35.2 + '@img/sharp-linux-arm64': 0.35.2 + '@img/sharp-linux-ppc64': 0.35.2 + '@img/sharp-linux-riscv64': 0.35.2 + '@img/sharp-linux-s390x': 0.35.2 + '@img/sharp-linux-x64': 0.35.2 + '@img/sharp-linuxmusl-arm64': 0.35.2 + '@img/sharp-linuxmusl-x64': 0.35.2 + '@img/sharp-webcontainers-wasm32': 0.35.2 + '@img/sharp-win32-arm64': 0.35.2 + '@img/sharp-win32-ia32': 0.35.2 + '@img/sharp-win32-x64': 0.35.2 + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -4364,6 +5185,8 @@ snapshots: strip-bom@3.0.0: {} + supports-color@10.2.2: {} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -4398,6 +5221,9 @@ snapshots: ts-algebra@2.0.0: {} + tslib@2.8.1: + optional: true + tsx@4.21.0: dependencies: esbuild: 0.27.3 @@ -4447,6 +5273,12 @@ snapshots: undici-types@6.21.0: {} + undici@7.29.0: {} + + unenv@2.0.0-rc.24: + dependencies: + pathe: 2.0.3 + universalify@0.1.2: {} unpipe@1.0.0: {} @@ -4578,6 +5410,31 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 + workerd@1.20260908.1: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20260908.1 + '@cloudflare/workerd-darwin-arm64': 1.20260908.1 + '@cloudflare/workerd-linux-64': 1.20260908.1 + '@cloudflare/workerd-linux-arm64': 1.20260908.1 + '@cloudflare/workerd-windows-64': 1.20260908.1 + + wrangler@4.130.0(@cloudflare/workers-types@5.20260908.1)(bufferutil@4.1.0)(utf-8-validate@5.0.10): + dependencies: + '@cloudflare/kv-asset-handler': 0.5.0 + '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260908.1) + blake3-wasm: 2.1.5 + esbuild: 0.28.1 + miniflare: 5.20260908.0-alpha(bufferutil@4.1.0)(utf-8-validate@5.0.10) + path-to-regexp: 6.3.0 + unenv: 2.0.0-rc.24 + workerd: 1.20260908.1 + optionalDependencies: + '@cloudflare/workers-types': 5.20260908.1 + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + wrap-ansi@9.0.2: dependencies: ansi-styles: 6.2.3 @@ -4591,14 +5448,26 @@ snapshots: bufferutil: 4.1.0 utf-8-validate: 5.0.10 - ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10): + ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@5.0.10): optionalDependencies: bufferutil: 4.1.0 utf-8-validate: 5.0.10 - optional: true yaml@2.8.2: {} + 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.24 + cookie: 1.1.1 + youch-core: 0.3.3 + zod-to-json-schema@3.25.1(zod@3.25.76): dependencies: zod: 3.25.76