diff --git a/integrations/ai-sdk-provider/README.md b/integrations/ai-sdk-provider/README.md index 69148953b..e242dd5a3 100644 --- a/integrations/ai-sdk-provider/README.md +++ b/integrations/ai-sdk-provider/README.md @@ -2,6 +2,11 @@ Databricks provider for the [Vercel AI SDK](https://sdk.vercel.ai/docs). +This package supports two integration styles: + +- **Language model provider** for Databricks serving endpoints +- **Genie conversation client and custom agent** for Databricks Genie conversation APIs + ## Features - 🚀 Support for all Databricks endpoint types: @@ -10,6 +15,7 @@ Databricks provider for the [Vercel AI SDK](https://sdk.vercel.ai/docs). - **Chat Agent** (`agent/v2/chat`) - Legacy Databricks chat agent API ([docs](https://docs.databricks.com/aws/en/generative-ai/agent-framework/agent-legacy-schema)) - 🔄 Stream and non-stream (generate) support for all endpoint types - 🛠️ Tool calling and agent support +- 💬 Genie conversation helper and custom AI SDK agent support - 🔐 Flexible authentication (bring your own tokens/headers) - 🎯 Full TypeScript support @@ -27,7 +33,7 @@ This package requires the following peer dependencies: npm install @ai-sdk/provider @ai-sdk/provider-utils ``` -To use the provider with AI SDK functions like `generateText` or `streamText`, also install: +To use the custom Genie agent with AI SDK agent utilities, also install: ```bash npm install ai @@ -58,6 +64,71 @@ const result = await generateText({ console.log(result.text) ``` +## Genie Quick Start + +```typescript +import { createAgentUIStreamResponse } from 'ai' +import { createDatabricksGenieAgent } from '@databricks/ai-sdk-provider' + +const genieAgent = createDatabricksGenieAgent({ + baseURL: 'https://your-workspace.databricks.com', + spaceId: 'your-genie-space-id', + headers: { + Authorization: `Bearer ${token}`, + }, +}) + +export async function POST(request: Request) { + const { messages } = await request.json() + + return createAgentUIStreamResponse({ + agent: genieAgent, + uiMessages: messages, + }) +} +``` + +The returned AI SDK result keeps Genie-specific metadata on `result.genie`, including: + +- `conversationId` +- `messageId` +- `status` +- `text` +- `sql` +- `attachmentId` +- `suggestedQuestions` +- optional `queryResult` + +## Genie Live Smoke Test + +You can run a real end-to-end smoke test against your Databricks workspace with: + +```bash +npm run test:genie:live +``` + +The test auto-loads `.env.local` from this package directory before execution. Set: + +```bash +DATABRICKS_HOST="https://your-workspace.databricks.com" +DATABRICKS_TOKEN="your-token" +DATABRICKS_GENIE_SPACE_ID="your-genie-space-id" +``` + +Optional environment variables: + +- `DATABRICKS_GENIE_TEST_QUESTION`: override the first Genie question +- `DATABRICKS_GENIE_TEST_FOLLOW_UP_QUESTION`: override the follow-up question sent through the agent + +The live smoke test: + +- auto-loads `.env.local` +- starts with the Genie conversation client +- logs raw and normalized attachment details +- uses Genie-suggested follow-up questions when they are available +- fetches tabular query results when Genie returns a query attachment +- sends a second follow-up through the Genie agent using the returned `conversationId` + ## Authentication The provider requires you to pass authentication headers: @@ -71,6 +142,9 @@ const provider = createDatabricksProvider({ }) ``` +The Genie conversation client and Genie agent use the same provider-style settings, but the `baseURL` +should be your workspace host rather than `/serving-endpoints`. + ## API Reference ### Main Export @@ -94,6 +168,63 @@ Creates a Databricks provider instance. - `chatCompletions(modelId: string)`: Create a Chat Completions model - `chatAgent(modelId: string)`: Create a Chat Agent model +### Genie Exports + +#### `createDatabricksGenieConversationClient(settings)` + +Creates a conversation-focused client for the Databricks Genie conversation API. + +**Parameters:** + +- `settings.baseURL` (string, required): Databricks workspace base URL +- `settings.spaceId` (string, required): Genie space ID +- `settings.headers` (object, optional): Custom headers to include in requests +- `settings.fetch` (function, optional): Custom fetch implementation +- `settings.formatUrl` (function, optional): Optional function to format the URL +- `settings.timeoutMs` (number, optional): Polling timeout, default `600000` +- `settings.initialPollIntervalMs` (number, optional): Initial polling delay, default `1000` +- `settings.maxPollIntervalMs` (number, optional): Maximum polling delay, default `60000` +- `settings.backoffMultiplier` (number, optional): Polling backoff multiplier, default `2` + +The conversation client exposes: + +- `startConversation(question)` +- `createMessage(conversationId, question)` +- `getMessage(conversationId, messageId)` +- `waitForCompletion(conversationId, messageId, options)` +- `getQueryResult(conversationId, messageId, attachmentId)` +- `ask(question, options)` + +`ask(question, options)` returns a normalized result with: + +- `conversationId` +- `messageId` +- `status` +- `text` +- `sql` +- `attachmentId` +- `suggestedQuestions` +- optional `queryResult` +- the normalized raw `message` + +#### `createDatabricksGenieAgent(settings)` + +Creates a custom AI SDK agent backed directly by the Databricks Genie conversation API. + +The agent: + +- sends only the latest user message as the new Genie question +- keeps Databricks conversation state via `conversationId` +- returns normal assistant text plus structured Genie metadata in `result.genie` +- supports `createAgentUIStreamResponse()` without requiring a new language-model provider + +Agent call options: + +- `conversationId?: string` +- `fetchQueryResult?: boolean` default `false` +- `headers?: Record` +- polling overrides: `timeoutMs`, `initialPollIntervalMs`, `maxPollIntervalMs`, `backoffMultiplier` + ### Remote Tool Calling The `useRemoteToolCalling` option controls how tool calls from Databricks agents are handled. When enabled, tool calls are marked as `dynamic: true` and `providerExecuted: true`, which tells the AI SDK that: diff --git a/integrations/ai-sdk-provider/package-lock.json b/integrations/ai-sdk-provider/package-lock.json index fa597a6a1..3769e9836 100644 --- a/integrations/ai-sdk-provider/package-lock.json +++ b/integrations/ai-sdk-provider/package-lock.json @@ -1,45 +1,68 @@ { "name": "@databricks/ai-sdk-provider", - "version": "0.5.1", + "version": "0.5.2-test.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@databricks/ai-sdk-provider", - "version": "0.5.1", + "version": "0.5.2-test.0", "license": "Databricks License", "dependencies": { - "zod": "^4.3.5" + "zod": "^4.3.6" }, "devDependencies": { - "@arethetypeswrong/cli": "^0.15.0", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.0.0", - "@typescript-eslint/parser": "^7.0.0", - "@vitest/coverage-v8": "^4.0.18", - "@vitest/ui": "^4.0.18", - "eslint": "^8.57.0", - "eslint-config-prettier": "^9.1.0", - "msw": "^2.0.0", - "prettier": "^3.0.0", - "tsdown": "^0.9.0", - "typescript": "^5.4.0", - "vitest": "^4.0.18" + "@ai-sdk/provider": "^3.0.5", + "@ai-sdk/provider-utils": "^4.0.10", + "@arethetypeswrong/cli": "0.18.2", + "@types/node": "25.6.0", + "@typescript-eslint/eslint-plugin": "8.58.1", + "@typescript-eslint/parser": "8.58.1", + "@vitest/coverage-v8": "4.1.4", + "@vitest/ui": "4.1.4", + "ai": "^6.0.0", + "dotenv": "^17.4.2", + "eslint": "8.57.1", + "eslint-config-prettier": "9.1.2", + "msw": "2.13.2", + "prettier": "3.8.2", + "tsdown": "0.21.7", + "typescript": "5.9.3", + "vitest": "4.1.4" }, "engines": { "node": ">=18.0.0" }, "peerDependencies": { "@ai-sdk/provider": "^3.0.5", - "@ai-sdk/provider-utils": "^4.0.10" + "@ai-sdk/provider-utils": "^4.0.10", + "ai": "^6.0.0" + } + }, + "node_modules/@ai-sdk/gateway": { + "version": "3.0.95", + "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-3.0.95.tgz", + "integrity": "sha512-ZmUNNbZl3V42xwQzPaNUi+s8eqR2lnrxf0bvB6YbLXpLjHYv0k2Y78t12cNOfY0bxGeuVVTLyk856uLuQIuXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "3.0.8", + "@ai-sdk/provider-utils": "4.0.23", + "@vercel/oidc": "3.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" } }, "node_modules/@ai-sdk/provider": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-3.0.5.tgz", - "integrity": "sha512-2Xmoq6DBJqmSl80U6V9z5jJSJP7ehaJJQMy2iFUqTay06wdCqTnPVBBQbtEL8RCChenL+q5DC5H5WzU3vV3v8w==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-3.0.8.tgz", + "integrity": "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==", + "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "json-schema": "^0.4.0" }, @@ -48,13 +71,13 @@ } }, "node_modules/@ai-sdk/provider-utils": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-4.0.10.tgz", - "integrity": "sha512-VeDAiCH+ZK8Xs4hb9Cw7pHlujWNL52RKe8TExOkrw6Ir1AmfajBZTb9XUdKOZO08RwQElIKA8+Ltm+Gqfo8djQ==", + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-4.0.23.tgz", + "integrity": "sha512-z8GlDaCmRSDlqkMF2f4/RFgWxdarvIbyuk+m6WXT1LYgsnGiXRJGTD2Z1+SDl3LqtFuRtGX1aghYvQLoHL/9pg==", + "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { - "@ai-sdk/provider": "3.0.5", + "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, @@ -72,13 +95,13 @@ "dev": true }, "node_modules/@arethetypeswrong/cli": { - "version": "0.15.4", - "resolved": "https://registry.npmjs.org/@arethetypeswrong/cli/-/cli-0.15.4.tgz", - "integrity": "sha512-YDbImAi1MGkouT7f2yAECpUMFhhA1J0EaXzIqoC5GGtK0xDgauLtcsZezm8tNq7d3wOFXH7OnY+IORYcG212rw==", + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/@arethetypeswrong/cli/-/cli-0.18.2.tgz", + "integrity": "sha512-PcFM20JNlevEDKBg4Re29Rtv2xvjvQZzg7ENnrWFSS0PHgdP2njibVFw+dRUhNkPgNfac9iUqO0ohAXqQL4hbw==", "dev": true, "license": "MIT", "dependencies": { - "@arethetypeswrong/core": "0.15.1", + "@arethetypeswrong/core": "0.18.2", "chalk": "^4.1.2", "cli-table3": "^0.6.3", "commander": "^10.0.1", @@ -90,31 +113,33 @@ "attw": "dist/index.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@arethetypeswrong/core": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@arethetypeswrong/core/-/core-0.15.1.tgz", - "integrity": "sha512-FYp6GBAgsNz81BkfItRz8RLZO03w5+BaeiPma1uCfmxTnxbtuMrI/dbzGiOk8VghO108uFI0oJo0OkewdSHw7g==", + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/@arethetypeswrong/core/-/core-0.18.2.tgz", + "integrity": "sha512-GiwTmBFOU1/+UVNqqCGzFJYfBXEytUkiI+iRZ6Qx7KmUVtLm00sYySkfe203C9QtPG11yOz1ZaMek8dT/xnlgg==", "dev": true, "license": "MIT", "dependencies": { "@andrewbranch/untar.js": "^1.0.3", + "@loaderkit/resolve": "^1.0.2", + "cjs-module-lexer": "^1.2.3", "fflate": "^0.8.2", + "lru-cache": "^11.0.1", "semver": "^7.5.4", - "ts-expose-internals-conditionally": "1.0.0-empty.0", - "typescript": "5.3.3", + "typescript": "5.6.1-rc", "validate-npm-package-name": "^5.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@arethetypeswrong/core/node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.6.1-rc", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.1-rc.tgz", + "integrity": "sha512-E3b2+1zEFu84jB0YQi9BORDjz9+jGbwwy1Zi3G0LUNw7a7cePUrHMRNy8aPh53nXpkFGVHSxIZo5vKTfYaFiBQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -126,20 +151,71 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-8.0.0-rc.3.tgz", + "integrity": "sha512-em37/13/nR320G4jab/nIIHZgc2Wz2y/D39lxnTyxB4/D/omPQncl/lSdlnJY1OhQcRGugTSIF2l/69o31C9dA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/parser": "^8.0.0-rc.3", + "@babel/types": "^8.0.0-rc.3", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", + "@types/jsesc": "^2.5.0", "jsesc": "^3.0.2" }, "engines": { - "node": ">=6.9.0" + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@babel/generator/node_modules/@babel/helper-string-parser": { + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-8.0.0-rc.3.tgz", + "integrity": "sha512-AmwWFx1m8G/a5cXkxLxTiWl+YEoWuoFLUCwqMlNuWO1tqAYITQAbCRPUkyBHv1VOFgfjVOqEj6L3u15J5ZCzTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@babel/generator/node_modules/@babel/helper-validator-identifier": { + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.0-rc.3.tgz", + "integrity": "sha512-8AWCJ2VJJyDFlGBep5GpaaQ9AAaE/FjAcrqI7jyssYhtL7WGV0DOKpJsQqM037xDbpRLHXsY8TwU7zDma7coOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@babel/generator/node_modules/@babel/parser": { + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.0-rc.3.tgz", + "integrity": "sha512-B20dvP3MfNc/XS5KKCHy/oyWl5IA6Cn9YjXRdDlCjNmUFrjvLXMNUfQq/QUy9fnG2gYkKKcrto2YaF9B32ToOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^8.0.0-rc.3" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@babel/generator/node_modules/@babel/types": { + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.0-rc.3.tgz", + "integrity": "sha512-mOm5ZrYmphGfqVWoH5YYMTITb3cDXsFgmvFlvkvWDMsR9X8RFnt7a0Wb6yNIdoFsiMO9WjYLq+U/FMtqIYAF8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^8.0.0-rc.3", + "@babel/helper-validator-identifier": "^8.0.0-rc.3" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@babel/helper-string-parser": { @@ -163,13 +239,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.5" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -179,9 +255,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "license": "MIT", "dependencies": { @@ -202,6 +278,13 @@ "node": ">=18" } }, + "node_modules/@braidai/lang": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@braidai/lang/-/lang-1.1.2.tgz", + "integrity": "sha512-qBcknbBufNHlui137Hft8xauQMTZDKdophmLFv05r2eNmdIv/MlPuP4TdUknHG68UdWLgVZwgxVe735HzJNIwA==", + "dev": true, + "license": "ISC" + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -214,21 +297,21 @@ } }, "node_modules/@emnapi/core": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", - "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.1.0", + "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", "dev": true, "license": "MIT", "optional": true, @@ -237,9 +320,9 @@ } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", "dev": true, "license": "MIT", "optional": true, @@ -247,1403 +330,436 @@ "tslib": "^2.4.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", - "cpu": [ - "ppc64" - ], + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", - "cpu": [ - "arm" - ], + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", - "cpu": [ - "arm64" - ], + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, "engines": { - "node": ">=18" + "node": ">=10.10.0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", - "cpu": [ - "x64" - ], + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", - "cpu": [ - "arm" - ], + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", - "cpu": [ - "arm64" - ], + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", - "cpu": [ - "ia32" - ], + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@inquirer/ansi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", + "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", - "cpu": [ - "arm64" - ], + "node_modules/@inquirer/confirm": { + "version": "5.1.21", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", + "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/core": { + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", + "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.3" + }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", - "cpu": [ - "arm64" - ], + "node_modules/@inquirer/figures": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", - "cpu": [ - "x64" - ], + "node_modules/@inquirer/type": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", + "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", - "cpu": [ - "arm64" - ], + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", - "cpu": [ - "x64" - ], + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", - "cpu": [ - "arm64" - ], + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } + "license": "MIT" }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", - "cpu": [ - "ia32" - ], + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", - "cpu": [ - "x64" - ], + "node_modules/@loaderkit/resolve": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@loaderkit/resolve/-/resolve-1.0.4.tgz", + "integrity": "sha512-rJzYKVcV4dxJv+vW6jlvagF8zvGxHJ2+HTr1e2qOejfmGhAApgJHl8Aog4mMszxceTRiKTTbnpgmTO1bEZHV/A==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "license": "ISC", + "dependencies": { + "@braidai/lang": "^1.0.0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "node_modules/@mswjs/interceptors": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.41.3.tgz", + "integrity": "sha512-cXu86tF4VQVfwz8W1SPbhoRyHJkti6mjH/XJIxp40jhO4j2k1m4KYrEykxqWPkFF3vrK4rgQppBh//AwyGSXPA==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", - "dev": true, - "license": "MIT", "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@inquirer/ansi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", - "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/confirm": { - "version": "5.1.21", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", - "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/core": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", - "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/figures": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", - "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/type": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", - "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@mswjs/interceptors": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.40.0.tgz", - "integrity": "sha512-EFd6cVbHsgLa6wa4RljGj6Wk75qoHxUSyc5asLyyPSyuhIcdS2Q3Phw6ImS1q+CkALthJRShiYfKANcQMuMqsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@open-draft/deferred-promise": "^2.2.0", - "@open-draft/logger": "^0.3.0", - "@open-draft/until": "^2.0.0", - "is-node-process": "^1.2.0", - "outvariant": "^1.4.3", - "strict-event-emitter": "^0.5.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@open-draft/deferred-promise": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", - "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@open-draft/logger": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", - "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-node-process": "^1.2.0", - "outvariant": "^1.4.0" - } - }, - "node_modules/@open-draft/until": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", - "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@oxc-project/types": { - "version": "0.66.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.66.0.tgz", - "integrity": "sha512-KF5Wlo2KzQ+jmuCtrGISZoUfdHom7qHavNfPLW2KkeYJfYMGwtiia8KjwtsvNJ49qRiXImOCkPeVPd4bMlbR7w==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" - } - }, - "node_modules/@oxc-resolver/binding-darwin-arm64": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-9.0.2.tgz", - "integrity": "sha512-MVyRgP2gzJJtAowjG/cHN3VQXwNLWnY+FpOEsyvDepJki1SdAX/8XDijM1yN6ESD1kr9uhBKjGelC6h3qtT+rA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@oxc-resolver/binding-darwin-x64": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-9.0.2.tgz", - "integrity": "sha512-7kV0EOFEZ3sk5Hjy4+bfA6XOQpCwbDiDkkHN4BHHyrBHsXxUR05EcEJPPL1WjItefg+9+8hrBmoK0xRoDs41+A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@oxc-resolver/binding-freebsd-x64": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-9.0.2.tgz", - "integrity": "sha512-6OvkEtRXrt8sJ4aVfxHRikjain9nV1clIsWtJ1J3J8NG1ZhjyJFgT00SCvqxbK+pzeWJq6XzHyTCN78ML+lY2w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-9.0.2.tgz", - "integrity": "sha512-aYpNL6o5IRAUIdoweW21TyLt54Hy/ZS9tvzNzF6ya1ckOQ8DLaGVPjGpmzxdNja9j/bbV6aIzBH7lNcBtiOTkQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-resolver/binding-linux-arm64-gnu": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-9.0.2.tgz", - "integrity": "sha512-RGFW4vCfKMFEIzb9VCY0oWyyY9tR1/o+wDdNePhiUXZU4SVniRPQaZ1SJ0sUFI1k25pXZmzQmIP6cBmazi/Dew==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-resolver/binding-linux-arm64-musl": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-9.0.2.tgz", - "integrity": "sha512-lxx/PibBfzqYvut2Y8N2D0Ritg9H8pKO+7NUSJb9YjR/bfk2KRmP8iaUz3zB0JhPtf/W3REs65oKpWxgflGToA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-resolver/binding-linux-riscv64-gnu": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-9.0.2.tgz", - "integrity": "sha512-yD28ptS/OuNhwkpXRPNf+/FvrO7lwURLsEbRVcL1kIE0GxNJNMtKgIE4xQvtKDzkhk6ZRpLho5VSrkkF+3ARTQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-resolver/binding-linux-s390x-gnu": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-9.0.2.tgz", - "integrity": "sha512-WBwEJdspoga2w+aly6JVZeHnxuPVuztw3fPfWrei2P6rNM5hcKxBGWKKT6zO1fPMCB4sdDkFohGKkMHVV1eryQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-resolver/binding-linux-x64-gnu": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-9.0.2.tgz", - "integrity": "sha512-a2z3/cbOOTUq0UTBG8f3EO/usFcdwwXnCejfXv42HmV/G8GjrT4fp5+5mVDoMByH3Ce3iVPxj1LmS6OvItKMYQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-resolver/binding-linux-x64-musl": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-9.0.2.tgz", - "integrity": "sha512-bHZF+WShYQWpuswB9fyxcgMIWVk4sZQT0wnwpnZgQuvGTZLkYJ1JTCXJMtaX5mIFHf69ngvawnwPIUA4Feil0g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@oxc-resolver/binding-wasm32-wasi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-9.0.2.tgz", - "integrity": "sha512-I5cSgCCh5nFozGSHz+PjIOfrqW99eUszlxKLgoNNzQ1xQ2ou9ZJGzcZ94BHsM9SpyYHLtgHljmOZxCT9bgxYNA==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.9" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-resolver/binding-win32-arm64-msvc": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-9.0.2.tgz", - "integrity": "sha512-5IhoOpPr38YWDWRCA5kP30xlUxbIJyLAEsAK7EMyUgqygBHEYLkElaKGgS0X5jRXUQ6l5yNxuW73caogb2FYaw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@oxc-resolver/binding-win32-x64-msvc": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-9.0.2.tgz", - "integrity": "sha512-Qc40GDkaad9rZksSQr2l/V9UubigIHsW69g94Gswc2sKYB3XfJXfIfyV8WTJ67u6ZMXsZ7BH1msSC6Aen75mCg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@oxc-transform/binding-darwin-arm64": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-darwin-arm64/-/binding-darwin-arm64-0.67.0.tgz", - "integrity": "sha512-P3zBMhpOQceNSys3/ZqvrjuRvcIbVzfGFN/tH34HlVkOjOmfGK1mOWjORsGAZtbgh1muXrF6mQETLzFjfYndXQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-darwin-x64": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-darwin-x64/-/binding-darwin-x64-0.67.0.tgz", - "integrity": "sha512-B52aeo/C3spYHcwFQ4nAbDkwbMKf0K6ncWM8GrVUgGu8PPECLBhjPCW11kPW/lt9FxwrdgVYVzPYlZ6wmJmpEA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-arm-gnueabihf": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.67.0.tgz", - "integrity": "sha512-5Ir1eQrC9lvj/rR1TJVGwOR4yLgXTLmfKHIfpVH7GGSQrzK7VMUfHWX+dAsX1VutaeE8puXIqtYvf9cHLw78dw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-arm64-gnu": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.67.0.tgz", - "integrity": "sha512-zTqfPET5+hZfJ3/dMqJboKxrpXMXk+j2HVdvX0wVhW2MI7n7hwELl+In6Yu20nXuEyJkNQlWHbNPCUfpM+cBWw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-arm64-musl": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.67.0.tgz", - "integrity": "sha512-jzz/ATUhZ8wetb4gm5GwzheZns3Qj1CZ+DIMmD8nBxQXszmTS/fqnAPpgzruyLqkXBUuUfF3pHv5f/UmuHReuQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-x64-gnu": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.67.0.tgz", - "integrity": "sha512-Qy2+tfglJ8yX6guC1EDAnuuzRZIXciXO9UwOewxyiahLxwuTpj/wvvZN3Cb1SA3c14zrwb2TNMZvaXS1/OS5Pg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-x64-musl": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-x64-musl/-/binding-linux-x64-musl-0.67.0.tgz", - "integrity": "sha512-tHoYgDIRhgvh+/wIrzAk3cUoj/LSSoJAdsZW9XRlaixFW/TF2puxRyaS1hRco0bcKTwotXl/eDYqZmhIfUyGRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-wasm32-wasi": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-wasm32-wasi/-/binding-wasm32-wasi-0.67.0.tgz", - "integrity": "sha512-ZPT+1HECf7WUnotodIuS8tvSkwaiCdC2DDw8HVRmlerbS6iPYIPKyBCvkSM4RyUx0kljZtB9AciLCkEbwy5/zA==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.9" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-win32-arm64-msvc": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.67.0.tgz", - "integrity": "sha512-+E3lOHCk4EuIk6IjshBAARknAUpgH+gHTtZxCPqK4AWYA+Tls2J6C0FVM48uZ4m3rZpAq8ZszM9JZVAkOaynBQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-win32-x64-msvc": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.67.0.tgz", - "integrity": "sha512-3pIIFb9g5aFrAODTQVJYitq+ONHgDJ4IYk/7pk+jsG6JpKUkURd0auUlxvriO11fFit5hdwy+wIbU4kBvyRUkg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.29", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", - "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", - "dev": true, - "license": "MIT" - }, - "node_modules/@quansync/fs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-1.0.0.tgz", - "integrity": "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "quansync": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sxzz" - } - }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-2F4bhDtV6CHBx7JMiT9xvmxkcZLHFmonfbli36RyfvgThDOAu92bis28zDTdguDY85lN/jBRKX/eOvX+T5hMkg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-8VMChhFLeD/oOAQUspFtxZaV7ctDob63w626kwvBBIHtlpY2Ohw4rsfjjtGckyrTCI/RROgZv/TVVEsG3GkgLw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-4W28EgaIidbWIpwB3hESMBfiOSs7LBFpJGa8JIV488qLEnTR/pqzxDEoOPobhRSJ1lJlv0vUgA8+DKBIldo2gw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-1ECtyzIKlAHikR7BhS4hk7Hxw8xCH6W3S+Sb74EM0vy5AqPvWSbgLfAwagYC7gNDcMMby3I757X7qih5fIrGiw==", - "cpu": [ - "arm" - ], + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.3.tgz", + "integrity": "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-wU1kp8qPRUKC8N82dNs3F5+UyKRww9TUEO5dQ5mxCb0cG+y4l5rVaXpMgvL0VuQahPVvTMs577QPhJGb4iDONw==", - "cpu": [ - "arm64" - ], + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-odDjO2UtEEMAzwmLHEOKylJjQa+em1REAO9H19PA+O+lPu6evVbre5bqu8qCjEtHG1Q034LpZR86imCP2arb/w==", - "cpu": [ - "arm64" - ], + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">= 8" + } }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-Ty2T67t2Oj1lg417ATRENxdk8Jkkksc/YQdCJyvkGqteHe60pSU2GGP/tLWGB+I0Ox+u387bzU/SmfmrHZk9aw==", - "cpu": [ - "x64" - ], + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-Fm1TxyeVE+gy74HM26CwbEOUndIoWAMgWkVDxYBD64tayvp5JvltpGHaqCg6x5i+X2F5XCDCItqwVlC7/mTxIw==", - "cpu": [ - "x64" - ], + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "license": "MIT" }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-AEZzTyGerfkffXmtv7kFJbHWkryNeolk0Br+yhH1wZyN6Tt6aebqICDL8KNRO2iExoEWzyYS6dPxh0QmvNTfUQ==", - "cpu": [ - "wasm32" - ], + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.4" - }, - "engines": { - "node": ">=14.21.3" + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" } }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-0lskDFKQwf5PMjl17qHAroU6oVU0Zn8NbAH/PdM9QB1emOzyFDGa20d4kESGeo3Uq7xOKXcTORJV/JwKIBORqw==", - "cpu": [ - "arm64" - ], + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "license": "MIT" }, - "node_modules/@rolldown/binding-win32-ia32-msvc": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-DfG1S0zGKnUfr95cNCmR4YPiZ/moS7Tob5eV+9r5JGeHZVWFHWwvJdR0jArj6Ty0LbBFDTVVB3iAvqRSji+l0Q==", - "cpu": [ - "ia32" - ], + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-5HZEtc8U2I1O903hXBynWtWaf+qzAFj66h5B7gOtVcvqIk+lKRVSupA85OdIvR7emrsYU25ikpfiU5Jhg9kTbQ==", - "cpu": [ - "x64" - ], + "node_modules/@oxc-project/types": { + "version": "0.122.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz", + "integrity": "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "funding": { + "url": "https://github.com/sponsors/Boshen" + } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", - "cpu": [ - "arm" - ], + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@quansync/fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-1.0.0.tgz", + "integrity": "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ] + "dependencies": { + "quansync": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.12.tgz", + "integrity": "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==", "cpu": [ "arm64" ], @@ -1652,12 +768,15 @@ "optional": true, "os": [ "android" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.12.tgz", + "integrity": "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==", "cpu": [ "arm64" ], @@ -1666,12 +785,15 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.12.tgz", + "integrity": "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==", "cpu": [ "x64" ], @@ -1680,26 +802,15 @@ "optional": true, "os": [ "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", - "cpu": [ - "arm64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.12.tgz", + "integrity": "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==", "cpu": [ "x64" ], @@ -1708,26 +819,15 @@ "optional": true, "os": [ "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", - "cpu": [ - "arm" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.12.tgz", + "integrity": "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==", "cpu": [ "arm" ], @@ -1736,194 +836,135 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", - "cpu": [ - "arm64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.12.tgz", + "integrity": "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", - "cpu": [ - "loong64" + "libc": [ + "glibc" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", - "cpu": [ - "loong64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.12.tgz", + "integrity": "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.12.tgz", + "integrity": "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==", "cpu": [ "ppc64" ], "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", - "cpu": [ - "riscv64" + "libc": [ + "glibc" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", - "cpu": [ - "riscv64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.12.tgz", + "integrity": "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==", "cpu": [ "s390x" ], "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", - "cpu": [ - "x64" + "libc": [ + "glibc" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.12.tgz", + "integrity": "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", - "cpu": [ - "x64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.12.tgz", + "integrity": "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==", "cpu": [ - "arm64" + "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ - "openharmony" - ] + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.12.tgz", + "integrity": "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==", "cpu": [ "arm64" ], @@ -1931,41 +972,50 @@ "license": "MIT", "optional": true, "os": [ - "win32" - ] + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.12.tgz", + "integrity": "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==", "cpu": [ - "ia32" + "wasm32" ], "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.1" + }, + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.12.tgz", + "integrity": "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==", "cpu": [ - "x64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.12.tgz", + "integrity": "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==", "cpu": [ "x64" ], @@ -1974,7 +1024,17 @@ "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.12.tgz", + "integrity": "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==", + "dev": true, + "license": "MIT" }, "node_modules/@sindresorhus/is": { "version": "4.6.0", @@ -1993,6 +1053,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, "license": "MIT" }, "node_modules/@tybys/wasm-util": { @@ -2031,14 +1092,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@types/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { - "version": "22.19.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz", - "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==", + "version": "25.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", + "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.19.0" } }, "node_modules/@types/statuses": { @@ -2049,122 +1117,159 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", - "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.1.tgz", + "integrity": "sha512-eSkwoemjo76bdXl2MYqtxg51HNwUSkWfODUOQ3PaTLZGh9uIWWFZIjyjaJnex7wXDu+TRx+ATsnSxdN9YWfRTQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/type-utils": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.58.1", + "@typescript-eslint/type-utils": "8.58.1", + "@typescript-eslint/utils": "8.58.1", + "@typescript-eslint/visitor-keys": "8.58.1", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@typescript-eslint/parser": "^8.58.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", - "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.1.tgz", + "integrity": "sha512-gGkiNMPqerb2cJSVcruigx9eHBlLG14fSdPdqMoOcBfh+vvn4iCq2C8MzUB89PrxOXk0y3GZ1yIWb9aOzL93bw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.58.1", + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/typescript-estree": "8.58.1", + "@typescript-eslint/visitor-keys": "8.58.1", + "debug": "^4.4.3" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.1.tgz", + "integrity": "sha512-gfQ8fk6cxhtptek+/8ZIqw8YrRW5048Gug8Ts5IYcMLCw18iUgrZAEY/D7s4hkI0FxEfGakKuPK/XUMPzPxi5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.58.1", + "@typescript-eslint/types": "^8.58.1", + "debug": "^4.4.3" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.1.tgz", + "integrity": "sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/visitor-keys": "8.58.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.1.tgz", + "integrity": "sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw==", + "dev": true, + "license": "MIT", "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", - "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.1.tgz", + "integrity": "sha512-HUFxvTJVroT+0rXVJC7eD5zol6ID+Sn5npVPWoFuHGg9Ncq5Q4EYstqR+UOqaNRFXi5TYkpXXkLhoCHe3G0+7w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/typescript-estree": "8.58.1", + "@typescript-eslint/utils": "8.58.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.1.tgz", + "integrity": "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw==", "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2172,75 +1277,88 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.1.tgz", + "integrity": "sha512-w4w7WR7GHOjqqPnvAYbazq+Y5oS68b9CzasGtnd6jIeOIeKUzYzupGTB2T4LTPSv4d+WPeccbxuneTFHYgAAWg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "@typescript-eslint/project-service": "8.58.1", + "@typescript-eslint/tsconfig-utils": "8.58.1", + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/visitor-keys": "8.58.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.1.tgz", + "integrity": "sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.58.1", + "@typescript-eslint/types": "8.58.1", + "@typescript-eslint/typescript-estree": "8.58.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "version": "8.58.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.1.tgz", + "integrity": "sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.58.1", + "eslint-visitor-keys": "^5.0.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", @@ -2248,40 +1366,40 @@ "dev": true, "license": "ISC" }, - "node_modules/@valibot/to-json-schema": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@valibot/to-json-schema/-/to-json-schema-1.0.0.tgz", - "integrity": "sha512-/9crJgPptVsGCL6X+JPDQyaJwkalSZ/52WuF8DiRUxJgcmpNdzYRfZ+gqMEP8W3CTVfuMWPqqvIgfwJ97f9Etw==", + "node_modules/@vercel/oidc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.1.0.tgz", + "integrity": "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==", "dev": true, - "license": "MIT", - "peerDependencies": { - "valibot": "^1.0.0" + "license": "Apache-2.0", + "engines": { + "node": ">= 20" } }, "node_modules/@vitest/coverage-v8": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.18.tgz", - "integrity": "sha512-7i+N2i0+ME+2JFZhfuz7Tg/FqKtilHjGyGvoHYQ6iLV0zahbsJ9sljC9OcFcPDbhYKCet+sG8SsVqlyGvPflZg==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.4.tgz", + "integrity": "sha512-x7FptB5oDruxNPDNY2+S8tCh0pcq7ymCe1gTHcsp733jYjrJl8V1gMUlVysuCD9Kz46Xz9t1akkv08dPcYDs1w==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.0.18", - "ast-v8-to-istanbul": "^0.3.10", + "@vitest/utils": "4.1.4", + "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.2.0", - "magicast": "^0.5.1", + "magicast": "^0.5.2", "obug": "^2.1.1", - "std-env": "^3.10.0", - "tinyrainbow": "^3.0.3" + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "4.0.18", - "vitest": "4.0.18" + "@vitest/browser": "4.1.4", + "vitest": "4.1.4" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -2290,31 +1408,31 @@ } }, "node_modules/@vitest/expect": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", - "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.4.tgz", + "integrity": "sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==", "dev": true, "license": "MIT", "dependencies": { - "@standard-schema/spec": "^1.0.0", + "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "chai": "^6.2.1", - "tinyrainbow": "^3.0.3" + "@vitest/spy": "4.1.4", + "@vitest/utils": "4.1.4", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/mocker": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", - "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.4.tgz", + "integrity": "sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.0.18", + "@vitest/spy": "4.1.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -2323,7 +1441,7 @@ }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0-0" + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "msw": { @@ -2335,26 +1453,26 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", - "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.4.tgz", + "integrity": "sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^3.0.3" + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", - "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.4.tgz", + "integrity": "sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.18", + "@vitest/utils": "4.1.4", "pathe": "^2.0.3" }, "funding": { @@ -2362,13 +1480,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", - "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.4.tgz", + "integrity": "sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", + "@vitest/pretty-format": "4.1.4", + "@vitest/utils": "4.1.4", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -2377,9 +1496,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", - "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.4.tgz", + "integrity": "sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ==", "dev": true, "license": "MIT", "funding": { @@ -2387,36 +1506,37 @@ } }, "node_modules/@vitest/ui": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-4.0.18.tgz", - "integrity": "sha512-CGJ25bc8fRi8Lod/3GHSvXRKi7nBo3kxh0ApW4yCjmrWmRmlT53B5E08XRSZRliygG0aVNxLrBEqPYdz/KcCtQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-4.1.4.tgz", + "integrity": "sha512-EgFR7nlj5iTDYZYCvavjFokNYwr3c3ry0sFiCg+N7B233Nwp+NNx7eoF/XvMWDCKY71xXAG3kFkt97ZHBJVL8A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.18", + "@vitest/utils": "4.1.4", "fflate": "^0.8.2", - "flatted": "^3.3.3", + "flatted": "^3.4.2", "pathe": "^2.0.3", "sirv": "^3.0.2", "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.0.3" + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "4.0.18" + "vitest": "4.1.4" } }, "node_modules/@vitest/utils": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", - "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.4.tgz", + "integrity": "sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", - "tinyrainbow": "^3.0.3" + "@vitest/pretty-format": "4.1.4", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -2445,10 +1565,29 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/ai": { + "version": "6.0.158", + "resolved": "https://registry.npmjs.org/ai/-/ai-6.0.158.tgz", + "integrity": "sha512-gLTp1UXFtMqKUi3XHs33K7UFglbvojkxF/aq337TxnLGOhHIW9+GyP2jwW4hYX87f1es+wId3VQoPRRu9zEStQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/gateway": "3.0.95", + "@ai-sdk/provider": "3.0.8", + "@ai-sdk/provider-utils": "4.0.23", + "@opentelemetry/api": "1.9.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -2508,9 +1647,9 @@ } }, "node_modules/ansis": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", - "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", "dev": true, "license": "ISC", "engines": { @@ -2531,16 +1670,6 @@ "dev": true, "license": "Python-2.0" }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -2552,32 +1681,83 @@ } }, "node_modules/ast-kit": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-1.4.3.tgz", - "integrity": "sha512-MdJqjpodkS5J149zN0Po+HPshkTdUyrvF7CKTafUgv69vBSPtncrj+3IiUgqdd7ElIEkbeXCsEouBUwLrw9Ilg==", + "version": "3.0.0-beta.1", + "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-3.0.0-beta.1.tgz", + "integrity": "sha512-trmleAnZ2PxN/loHWVhhx1qeOHSRXq4TDsBBxq3GqeJitfk3+jTQ+v/C1km/KYq9M7wKqCewMh+/NAvVH7m+bw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.0", + "@babel/parser": "^8.0.0-beta.4", + "estree-walker": "^3.0.3", "pathe": "^2.0.3" }, "engines": { - "node": ">=16.14.0" + "node": ">=20.19.0" }, "funding": { "url": "https://github.com/sponsors/sxzz" } }, + "node_modules/ast-kit/node_modules/@babel/helper-string-parser": { + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-8.0.0-rc.3.tgz", + "integrity": "sha512-AmwWFx1m8G/a5cXkxLxTiWl+YEoWuoFLUCwqMlNuWO1tqAYITQAbCRPUkyBHv1VOFgfjVOqEj6L3u15J5ZCzTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/ast-kit/node_modules/@babel/helper-validator-identifier": { + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.0-rc.3.tgz", + "integrity": "sha512-8AWCJ2VJJyDFlGBep5GpaaQ9AAaE/FjAcrqI7jyssYhtL7WGV0DOKpJsQqM037xDbpRLHXsY8TwU7zDma7coOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/ast-kit/node_modules/@babel/parser": { + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.0-rc.3.tgz", + "integrity": "sha512-B20dvP3MfNc/XS5KKCHy/oyWl5IA6Cn9YjXRdDlCjNmUFrjvLXMNUfQq/QUy9fnG2gYkKKcrto2YaF9B32ToOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^8.0.0-rc.3" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/ast-kit/node_modules/@babel/types": { + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.0-rc.3.tgz", + "integrity": "sha512-mOm5ZrYmphGfqVWoH5YYMTITb3cDXsFgmvFlvkvWDMsR9X8RFnt7a0Wb6yNIdoFsiMO9WjYLq+U/FMtqIYAF8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^8.0.0-rc.3", + "@babel/helper-validator-identifier": "^8.0.0-rc.3" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/ast-v8-to-istanbul": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.10.tgz", - "integrity": "sha512-p4K7vMz2ZSk3wN8l5o3y2bJAoZXT3VuJI5OLTATY/01CYWumWvwkUw0SqDBnNq6IiTO3qDa1eSQDibAV8g7XOQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.0.tgz", + "integrity": "sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.31", "estree-walker": "^3.0.3", - "js-tokens": "^9.0.1" + "js-tokens": "^10.0.0" } }, "node_modules/balanced-match": { @@ -2587,37 +1767,24 @@ "dev": true, "license": "MIT" }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/birpc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-4.0.0.tgz", + "integrity": "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==", "dev": true, "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cac/-/cac-7.0.0.tgz", + "integrity": "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=20.19.0" } }, "node_modules/callsites": { @@ -2667,21 +1834,12 @@ "node": ">=10" } }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } + "license": "MIT" }, "node_modules/cli-highlight": { "version": "2.1.11", @@ -2798,15 +1956,12 @@ "dev": true, "license": "MIT" }, - "node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "MIT", - "engines": { - "node": "^14.18.0 || >=16.10.0" - } + "license": "MIT" }, "node_modules/cookie": { "version": "1.1.1", @@ -2863,9 +2018,9 @@ "license": "MIT" }, "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", "dev": true, "license": "MIT" }, @@ -2879,29 +2034,6 @@ "node": ">=8" } }, - "node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2915,21 +2047,38 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dts-resolver": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/dts-resolver/-/dts-resolver-1.2.0.tgz", - "integrity": "sha512-+xNF7raXYI1E3IFB+f3JqvoKYFI8R+1Mh9mpI75yNm3F5XuiC6ErEXe2Lqh9ach+4MQ1tOefzjxulhWGVclYbg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/dts-resolver/-/dts-resolver-2.1.3.tgz", + "integrity": "sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==", "dev": true, "license": "MIT", - "dependencies": { - "oxc-resolver": "^9.0.0", - "pathe": "^2.0.3" - }, "engines": { - "node": ">=20.18.0" + "node": ">=20.19.0" }, "funding": { "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "oxc-resolver": ">=11.0.0" + }, + "peerDependenciesMeta": { + "oxc-resolver": { + "optional": true + } } }, "node_modules/emoji-regex": { @@ -2947,9 +2096,9 @@ "license": "MIT" }, "node_modules/empathic": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/empathic/-/empathic-1.1.0.tgz", - "integrity": "sha512-rsPft6CK3eHtrlp9Y5ALBb+hfK+DWnA4WFebbazxjWyx8vSm3rZeoM3z9irsjcqO3PYRzlfv27XIB4tz2DV7RA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", "dev": true, "license": "MIT", "engines": { @@ -2970,54 +2119,12 @@ } }, "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, - "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -3142,9 +2249,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -3243,8 +2350,8 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", + "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=18.0.0" } @@ -3264,37 +2371,7 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } + "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", @@ -3340,19 +2417,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3386,9 +2450,9 @@ } }, "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, @@ -3425,9 +2489,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "version": "4.13.7", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", + "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3473,9 +2537,9 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -3512,27 +2576,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -3541,9 +2584,9 @@ "license": "MIT" }, "node_modules/graphql": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz", - "integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==", + "version": "16.13.2", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.2.tgz", + "integrity": "sha512-5bJ+nf/UCpAjHM8i06fl7eLyVC9iuNAjm9qzkiu2ZGhM0VscSvS6WDPfAwkdkBuoXGM9FJSbKl6wylMwP9Ktig==", "dev": true, "license": "MIT", "engines": { @@ -3578,9 +2621,9 @@ } }, "node_modules/hookable": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", - "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-6.1.0.tgz", + "integrity": "sha512-ZoKZSJgu8voGK2geJS+6YtYjvIzu9AOM/KZXsBxr83uhLL++e9pEv/dlgwgy3dvHg06kTz6JOh1hk3C8Ceiymw==", "dev": true, "license": "MIT" }, @@ -3618,6 +2661,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-without-cache": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/import-without-cache/-/import-without-cache-0.2.5.tgz", + "integrity": "sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -3687,16 +2743,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -3753,20 +2799,10 @@ "node": ">=8" } }, - "node_modules/jiti": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, "node_modules/js-tokens": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", - "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", "dev": true, "license": "MIT" }, @@ -3807,8 +2843,8 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)", - "peer": true + "dev": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -3849,9 +2885,9 @@ } }, "node_modules/lightningcss": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", - "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -3865,23 +2901,23 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-android-arm64": "1.30.2", - "lightningcss-darwin-arm64": "1.30.2", - "lightningcss-darwin-x64": "1.30.2", - "lightningcss-freebsd-x64": "1.30.2", - "lightningcss-linux-arm-gnueabihf": "1.30.2", - "lightningcss-linux-arm64-gnu": "1.30.2", - "lightningcss-linux-arm64-musl": "1.30.2", - "lightningcss-linux-x64-gnu": "1.30.2", - "lightningcss-linux-x64-musl": "1.30.2", - "lightningcss-win32-arm64-msvc": "1.30.2", - "lightningcss-win32-x64-msvc": "1.30.2" + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" } }, "node_modules/lightningcss-android-arm64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", - "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", "cpu": [ "arm64" ], @@ -3900,9 +2936,9 @@ } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", - "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", "cpu": [ "arm64" ], @@ -3921,9 +2957,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", - "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", "cpu": [ "x64" ], @@ -3942,9 +2978,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", - "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", "cpu": [ "x64" ], @@ -3963,9 +2999,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", - "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", "cpu": [ "arm" ], @@ -3984,13 +3020,16 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", - "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -4005,13 +3044,16 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", - "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -4026,13 +3068,16 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", - "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -4047,13 +3092,16 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", - "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -4068,9 +3116,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", - "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", "cpu": [ "arm64" ], @@ -4089,9 +3137,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", - "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", "cpu": [ "x64" ], @@ -4132,6 +3180,16 @@ "dev": true, "license": "MIT" }, + "node_modules/lru-cache": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.3.tgz", + "integrity": "sha512-JvNw9Y81y33E+BEYPr0U7omo+U9AySnsMsEiXgwT6yqd31VQWTLNQqmT4ou5eqPFUrTfIDFta2wKhB1hyohtAQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -4143,14 +3201,14 @@ } }, "node_modules/magicast": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz", - "integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", + "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", "source-map-js": "^1.2.1" } }, @@ -4218,44 +3276,43 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, "engines": { - "node": ">= 8" + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "node_modules/minimatch/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, "engines": { - "node": ">=8.6" + "node": "18 || 20 || >=22" } }, - "node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "node_modules/minimatch/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.2" + "balanced-match": "^4.0.2" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "18 || 20 || >=22" } }, "node_modules/mrmime": { @@ -4276,15 +3333,15 @@ "license": "MIT" }, "node_modules/msw": { - "version": "2.12.7", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.7.tgz", - "integrity": "sha512-retd5i3xCZDVWMYjHEVuKTmhqY8lSsxujjVrZiGbbdoxxIBg5S7rCuYy/YQpfrTYIxpd/o0Kyb/3H+1udBMoYg==", + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.13.2.tgz", + "integrity": "sha512-go2H1TIERKkC48pXiwec5l6sbNqYuvqOk3/vHGo1Zd+pq/H63oFawDQerH+WQdUw/flJFHDG7F+QdWMwhntA/A==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { "@inquirer/confirm": "^5.0.0", - "@mswjs/interceptors": "^0.40.0", + "@mswjs/interceptors": "^0.41.2", "@open-draft/deferred-promise": "^2.2.0", "@types/statuses": "^2.0.6", "cookie": "^1.0.2", @@ -4294,7 +3351,7 @@ "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", - "rettime": "^0.7.0", + "rettime": "^0.10.1", "statuses": "^2.0.2", "strict-event-emitter": "^0.5.1", "tough-cookie": "^6.0.0", @@ -4336,9 +3393,9 @@ } }, "node_modules/msw/node_modules/type-fest": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.3.1.tgz", - "integrity": "sha512-VCn+LMHbd4t6sF3wfU/+HKT63C9OoyrSIf4b+vtWHpt2U7/4InZG467YDNMFMR70DdHjAdpPWmw2lzRdg0Xqqg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.5.0.tgz", + "integrity": "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==", "dev": true, "license": "(MIT OR CC0-1.0)", "dependencies": { @@ -4518,56 +3575,6 @@ "dev": true, "license": "MIT" }, - "node_modules/oxc-resolver": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-9.0.2.tgz", - "integrity": "sha512-w838ygc1p7rF+7+h5vR9A+Y9Fc4imy6C3xPthCMkdFUgFvUWkmABeNB8RBDQ6+afk44Q60/UMMQ+gfDUW99fBA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" - }, - "optionalDependencies": { - "@oxc-resolver/binding-darwin-arm64": "9.0.2", - "@oxc-resolver/binding-darwin-x64": "9.0.2", - "@oxc-resolver/binding-freebsd-x64": "9.0.2", - "@oxc-resolver/binding-linux-arm-gnueabihf": "9.0.2", - "@oxc-resolver/binding-linux-arm64-gnu": "9.0.2", - "@oxc-resolver/binding-linux-arm64-musl": "9.0.2", - "@oxc-resolver/binding-linux-riscv64-gnu": "9.0.2", - "@oxc-resolver/binding-linux-s390x-gnu": "9.0.2", - "@oxc-resolver/binding-linux-x64-gnu": "9.0.2", - "@oxc-resolver/binding-linux-x64-musl": "9.0.2", - "@oxc-resolver/binding-wasm32-wasi": "9.0.2", - "@oxc-resolver/binding-win32-arm64-msvc": "9.0.2", - "@oxc-resolver/binding-win32-x64-msvc": "9.0.2" - } - }, - "node_modules/oxc-transform": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/oxc-transform/-/oxc-transform-0.67.0.tgz", - "integrity": "sha512-QXwmpLfNrXZoHgIjEtDEf6lhwmvHouNtstNgg/UveczVIjo8VSzd5h25Ea96PoX9KzReJUY/qYa4QSNkJpZGfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/Boshen" - }, - "optionalDependencies": { - "@oxc-transform/binding-darwin-arm64": "0.67.0", - "@oxc-transform/binding-darwin-x64": "0.67.0", - "@oxc-transform/binding-linux-arm-gnueabihf": "0.67.0", - "@oxc-transform/binding-linux-arm64-gnu": "0.67.0", - "@oxc-transform/binding-linux-arm64-musl": "0.67.0", - "@oxc-transform/binding-linux-x64-gnu": "0.67.0", - "@oxc-transform/binding-linux-x64-musl": "0.67.0", - "@oxc-transform/binding-wasm32-wasi": "0.67.0", - "@oxc-transform/binding-win32-arm64-msvc": "0.67.0", - "@oxc-transform/binding-win32-x64-msvc": "0.67.0" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -4674,16 +3681,6 @@ "dev": true, "license": "MIT" }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -4699,22 +3696,22 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", + "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", "dev": true, "funding": [ { @@ -4751,9 +3748,9 @@ } }, "node_modules/prettier": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", - "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.2.tgz", + "integrity": "sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q==", "dev": true, "license": "MIT", "bin": { @@ -4814,20 +3811,6 @@ ], "license": "MIT" }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4859,9 +3842,9 @@ } }, "node_modules/rettime": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rettime/-/rettime-0.7.0.tgz", - "integrity": "sha512-LPRKoHnLKd/r3dVxcwO7vhCW+orkOGj9ViueosEBK6ie89CijnfRlhaDhHq/3Hxu4CkWQtxwlBG0mzTQY6uQjw==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/rettime/-/rettime-0.10.1.tgz", + "integrity": "sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw==", "dev": true, "license": "MIT" }, @@ -4894,119 +3877,133 @@ } }, "node_modules/rolldown": { - "version": "1.0.0-beta.8-commit.151352b", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.8-commit.151352b.tgz", - "integrity": "sha512-TCb6GVaFBk4wB0LERofFDxTO5X1/Sgahr7Yn5UA9XjuFtCwL1CyEhUHX5lUIstcMxjbkLjn2z4TAGwisr6Blvw==", + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.12.tgz", + "integrity": "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==", "dev": true, - "hasInstallScript": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "0.66.0", - "@valibot/to-json-schema": "1.0.0", - "ansis": "^3.17.0", - "valibot": "1.0.0" + "@oxc-project/types": "=0.122.0", + "@rolldown/pluginutils": "1.0.0-rc.12" }, "bin": { "rolldown": "bin/cli.mjs" }, - "optionalDependencies": { - "@rolldown/binding-darwin-arm64": "1.0.0-beta.8-commit.151352b", - "@rolldown/binding-darwin-x64": "1.0.0-beta.8-commit.151352b", - "@rolldown/binding-freebsd-x64": "1.0.0-beta.8-commit.151352b", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.8-commit.151352b", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.8-commit.151352b", - "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.8-commit.151352b", - "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.8-commit.151352b", - "@rolldown/binding-linux-x64-musl": "1.0.0-beta.8-commit.151352b", - "@rolldown/binding-wasm32-wasi": "1.0.0-beta.8-commit.151352b", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.8-commit.151352b", - "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.8-commit.151352b", - "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.8-commit.151352b" - }, - "peerDependencies": { - "@oxc-project/runtime": "0.66.0" + "engines": { + "node": "^20.19.0 || >=22.12.0" }, - "peerDependenciesMeta": { - "@oxc-project/runtime": { - "optional": true - } + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-rc.12", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.12", + "@rolldown/binding-darwin-x64": "1.0.0-rc.12", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.12", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12" } }, "node_modules/rolldown-plugin-dts": { - "version": "0.9.11", - "resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.9.11.tgz", - "integrity": "sha512-iCIRKmvPLwRV4UKSxhaBo+5wDkvc3+MFiqYYvu7sGLSohzxoDn9WEsjN3y7A6xg3aCuxHh6rlRp8xbX98r1rSg==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.23.2.tgz", + "integrity": "sha512-PbSqLawLgZBGcOGT3yqWBGn4cX+wh2nt5FuBGdcMHyOhoukmjbhYAl8NT9sE4U38Cm9tqLOIQeOrvzeayM0DLQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/generator": "^7.27.1", - "@babel/parser": "^7.27.1", - "@babel/types": "^7.27.1", - "ast-kit": "^1.4.3", - "debug": "^4.4.0", - "dts-resolver": "^1.0.1", - "get-tsconfig": "^4.10.0", - "oxc-transform": "^0.67.0" + "@babel/generator": "8.0.0-rc.3", + "@babel/helper-validator-identifier": "8.0.0-rc.3", + "@babel/parser": "8.0.0-rc.3", + "@babel/types": "8.0.0-rc.3", + "ast-kit": "^3.0.0-beta.1", + "birpc": "^4.0.0", + "dts-resolver": "^2.1.3", + "get-tsconfig": "^4.13.7", + "obug": "^2.1.1", + "picomatch": "^4.0.4" }, "engines": { - "node": ">=20.18.0" + "node": ">=20.19.0" }, "funding": { "url": "https://github.com/sponsors/sxzz" }, "peerDependencies": { - "rolldown": "^1.0.0-beta.7", - "typescript": "^5.0.0" + "@ts-macro/tsc": "^0.3.6", + "@typescript/native-preview": ">=7.0.0-dev.20260325.1", + "rolldown": "^1.0.0-rc.12", + "typescript": "^5.0.0 || ^6.0.0", + "vue-tsc": "~3.2.0" }, "peerDependenciesMeta": { + "@ts-macro/tsc": { + "optional": true + }, + "@typescript/native-preview": { + "optional": true + }, "typescript": { "optional": true + }, + "vue-tsc": { + "optional": true } } }, - "node_modules/rollup": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "node_modules/rolldown-plugin-dts/node_modules/@babel/helper-string-parser": { + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-8.0.0-rc.3.tgz", + "integrity": "sha512-AmwWFx1m8G/a5cXkxLxTiWl+YEoWuoFLUCwqMlNuWO1tqAYITQAbCRPUkyBHv1VOFgfjVOqEj6L3u15J5ZCzTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown-plugin-dts/node_modules/@babel/helper-validator-identifier": { + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.0-rc.3.tgz", + "integrity": "sha512-8AWCJ2VJJyDFlGBep5GpaaQ9AAaE/FjAcrqI7jyssYhtL7WGV0DOKpJsQqM037xDbpRLHXsY8TwU7zDma7coOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown-plugin-dts/node_modules/@babel/parser": { + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.0-rc.3.tgz", + "integrity": "sha512-B20dvP3MfNc/XS5KKCHy/oyWl5IA6Cn9YjXRdDlCjNmUFrjvLXMNUfQq/QUy9fnG2gYkKKcrto2YaF9B32ToOQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@babel/types": "^8.0.0-rc.3" }, "bin": { - "rollup": "dist/bin/rollup" + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/rolldown-plugin-dts/node_modules/@babel/types": { + "version": "8.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.0-rc.3.tgz", + "integrity": "sha512-mOm5ZrYmphGfqVWoH5YYMTITb3cDXsFgmvFlvkvWDMsR9X8RFnt7a0Wb6yNIdoFsiMO9WjYLq+U/FMtqIYAF8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^8.0.0-rc.3", + "@babel/helper-validator-identifier": "^8.0.0-rc.3" }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", - "fsevents": "~2.3.2" + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, "node_modules/run-parallel": { @@ -5034,9 +4031,9 @@ } }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -5117,16 +4114,6 @@ "node": ">=8" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -5155,9 +4142,9 @@ } }, "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", "dev": true, "license": "MIT" }, @@ -5300,9 +4287,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", + "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", "dev": true, "license": "MIT", "engines": { @@ -5344,23 +4331,10 @@ } } }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/tinyrainbow": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", - "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", "dev": true, "license": "MIT", "engines": { @@ -5368,38 +4342,25 @@ } }, "node_modules/tldts": { - "version": "7.0.19", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.19.tgz", - "integrity": "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==", + "version": "7.0.28", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.28.tgz", + "integrity": "sha512-+Zg3vWhRUv8B1maGSTFdev9mjoo8Etn2Ayfs4cnjlD3CsGkxXX4QyW3j2WJ0wdjYcYmy7Lx2RDsZMhgCWafKIw==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^7.0.19" + "tldts-core": "^7.0.28" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.0.19", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.19.tgz", - "integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==", + "version": "7.0.28", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.28.tgz", + "integrity": "sha512-7W5Efjhsc3chVdFhqtaU0KtK32J37Zcr9RKtID54nG+tIpcY79CQK/veYPODxtD/LJ4Lue66jvrQzIX2Z2/pUQ==", "dev": true, "license": "MIT" }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -5411,9 +4372,9 @@ } }, "node_modules/tough-cookie": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", - "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", + "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5423,66 +4384,90 @@ "node": ">=16" } }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, - "node_modules/ts-expose-internals-conditionally": { - "version": "1.0.0-empty.0", - "resolved": "https://registry.npmjs.org/ts-expose-internals-conditionally/-/ts-expose-internals-conditionally-1.0.0-empty.0.tgz", - "integrity": "sha512-F8m9NOF6ZhdOClDVdlM8gj3fDCav4ZIFSs/EI3ksQbAAXVSCN/Jh5OCJDDZWBuBy9psFc6jULGDlPwjMYMhJDw==", - "dev": true, - "license": "MIT" - }, "node_modules/tsdown": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/tsdown/-/tsdown-0.9.9.tgz", - "integrity": "sha512-IIGX55rkhaPomNSVrIbA58DRBwTO4ehlDTsw20XSooGqoEZbwpunDc1dRE73wKb1rHdwwBO6NMLOcgV2n1qhpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansis": "^3.17.0", - "cac": "^6.7.14", - "chokidar": "^4.0.3", - "consola": "^3.4.2", - "debug": "^4.4.0", - "diff": "^7.0.0", - "empathic": "^1.0.0", - "hookable": "^5.5.3", - "lightningcss": "^1.29.3", - "rolldown": "1.0.0-beta.8-commit.151352b", - "rolldown-plugin-dts": "^0.9.4", - "tinyexec": "^1.0.1", - "tinyglobby": "^0.2.13", - "unconfig": "^7.3.2", - "unplugin-lightningcss": "^0.3.3" + "version": "0.21.7", + "resolved": "https://registry.npmjs.org/tsdown/-/tsdown-0.21.7.tgz", + "integrity": "sha512-ukKIxKQzngkWvOYJAyptudclkm4VQqbjq+9HF5K5qDO8GJsYtMh8gIRwicbnZEnvFPr6mquFwYAVZ8JKt3rY2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansis": "^4.2.0", + "cac": "^7.0.0", + "defu": "^6.1.4", + "empathic": "^2.0.0", + "hookable": "^6.1.0", + "import-without-cache": "^0.2.5", + "obug": "^2.1.1", + "picomatch": "^4.0.4", + "rolldown": "1.0.0-rc.12", + "rolldown-plugin-dts": "^0.23.2", + "semver": "^7.7.4", + "tinyexec": "^1.0.4", + "tinyglobby": "^0.2.15", + "tree-kill": "^1.2.2", + "unconfig-core": "^7.5.0", + "unrun": "^0.2.34" }, "bin": { - "tsdown": "dist/run.js" + "tsdown": "dist/run.mjs" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.19.0" }, "funding": { "url": "https://github.com/sponsors/sxzz" }, "peerDependencies": { + "@arethetypeswrong/core": "^0.18.1", + "@tsdown/css": "0.21.7", + "@tsdown/exe": "0.21.7", + "@vitejs/devtools": "*", "publint": "^0.3.0", - "unplugin-unused": "^0.4.0" + "typescript": "^5.0.0 || ^6.0.0", + "unplugin-unused": "^0.5.0" }, "peerDependenciesMeta": { + "@arethetypeswrong/core": { + "optional": true + }, + "@tsdown/css": { + "optional": true + }, + "@tsdown/exe": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, "publint": { "optional": true }, + "typescript": { + "optional": true + }, "unplugin-unused": { "optional": true } @@ -5536,27 +4521,10 @@ "node": ">=14.17" } }, - "node_modules/unconfig": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-7.4.2.tgz", - "integrity": "sha512-nrMlWRQ1xdTjSnSUqvYqJzbTBFugoqHobQj58B2bc8qxHKBBHMNNsWQFP3Cd3/JZK907voM2geYPWqD4VK3MPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@quansync/fs": "^1.0.0", - "defu": "^6.1.4", - "jiti": "^2.6.1", - "quansync": "^1.0.0", - "unconfig-core": "7.4.2" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/unconfig-core": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.4.2.tgz", - "integrity": "sha512-VgPCvLWugINbXvMQDf8Jh0mlbvNjNC6eSUziHsBCMpxR05OPrNrvDnyatdMjRgcHaaNsCqz+wjNXxNw1kRLHUg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.5.0.tgz", + "integrity": "sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==", "dev": true, "license": "MIT", "dependencies": { @@ -5568,9 +4536,9 @@ } }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", + "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", "dev": true, "license": "MIT" }, @@ -5584,51 +4552,31 @@ "node": ">=4" } }, - "node_modules/unplugin": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.11.tgz", - "integrity": "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==", + "node_modules/unrun": { + "version": "0.2.34", + "resolved": "https://registry.npmjs.org/unrun/-/unrun-0.2.34.tgz", + "integrity": "sha512-LyaghRBR++r7svhDK6tnDz2XaYHWdneBOA0jbS8wnRsHerI9MFljX4fIiTgbbNbEVzZ0C9P1OjWLLe1OqoaaEw==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "acorn": "^8.15.0", - "picomatch": "^4.0.3", - "webpack-virtual-modules": "^0.6.2" + "rolldown": "1.0.0-rc.12" }, - "engines": { - "node": ">=18.12.0" - } - }, - "node_modules/unplugin-lightningcss": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/unplugin-lightningcss/-/unplugin-lightningcss-0.3.3.tgz", - "integrity": "sha512-mMNRCNIcxc/3410w7sJdXcPxn0IGZdEpq42OBDyckdGkhOeWYZCG9RkHs72TFyBsS82a4agFDOFU8VrFKF2ZvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "lightningcss": "^1.29.3", - "magic-string": "^0.30.17", - "unplugin": "^2.3.2" + "bin": { + "unrun": "dist/cli.mjs" }, "engines": { - "node": ">=18.12.0" + "node": ">=20.19.0" }, "funding": { - "url": "https://github.com/sponsors/sxzz" - } - }, - "node_modules/unplugin/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "url": "https://github.com/sponsors/Gugustinette" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "peerDependencies": { + "synckit": "^0.11.11" + }, + "peerDependenciesMeta": { + "synckit": { + "optional": true + } } }, "node_modules/until-async": { @@ -5645,25 +4593,10 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/valibot": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.0.0.tgz", - "integrity": "sha512-1Hc0ihzWxBar6NGeZv7fPLY0QuxFMyxwYR2sF1Blu7Wq7EnremwY2W02tit2ij2VJT8HcSkHAQqmFfl77f73Yw==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "typescript": ">=5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" } }, "node_modules/validate-npm-package-name": { @@ -5677,17 +4610,16 @@ } }, "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.8.tgz", + "integrity": "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.8", + "rolldown": "1.0.0-rc.15", "tinyglobby": "^0.2.15" }, "bin": { @@ -5704,9 +4636,10 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.0", + "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", - "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", @@ -5719,13 +4652,16 @@ "@types/node": { "optional": true }, - "jiti": { + "@vitejs/devtools": { "optional": true }, - "less": { + "esbuild": { "optional": true }, - "lightningcss": { + "jiti": { + "optional": true + }, + "less": { "optional": true }, "sass": { @@ -5751,63 +4687,358 @@ } } }, - "node_modules/vite/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/vite/node_modules/@oxc-project/types": { + "version": "0.124.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.124.0.tgz", + "integrity": "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.15.tgz", + "integrity": "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.15.tgz", + "integrity": "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.15.tgz", + "integrity": "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.15.tgz", + "integrity": "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.15.tgz", + "integrity": "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.15.tgz", + "integrity": "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.15.tgz", + "integrity": "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.15.tgz", + "integrity": "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.15.tgz", + "integrity": "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.15.tgz", + "integrity": "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.15.tgz", + "integrity": "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.15.tgz", + "integrity": "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.15.tgz", + "integrity": "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.9.2", + "@emnapi/runtime": "1.9.2", + "@napi-rs/wasm-runtime": "^1.1.3" }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "engines": { + "node": ">=14.0.0" } }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "node_modules/vite/node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.15.tgz", + "integrity": "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12" + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.15.tgz", + "integrity": "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.15.tgz", + "integrity": "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite/node_modules/rolldown": { + "version": "1.0.0-rc.15", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.15.tgz", + "integrity": "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.124.0", + "@rolldown/pluginutils": "1.0.0-rc.15" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-rc.15", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.15", + "@rolldown/binding-darwin-x64": "1.0.0-rc.15", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.15", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.15", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.15", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.15", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15" } }, "node_modules/vitest": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", - "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.4.tgz", + "integrity": "sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.0.18", - "@vitest/mocker": "4.0.18", - "@vitest/pretty-format": "4.0.18", - "@vitest/runner": "4.0.18", - "@vitest/snapshot": "4.0.18", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "es-module-lexer": "^1.7.0", - "expect-type": "^1.2.2", + "@vitest/expect": "4.1.4", + "@vitest/mocker": "4.1.4", + "@vitest/pretty-format": "4.1.4", + "@vitest/runner": "4.1.4", + "@vitest/snapshot": "4.1.4", + "@vitest/spy": "4.1.4", + "@vitest/utils": "4.1.4", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", - "std-env": "^3.10.0", + "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.0.3", - "vite": "^6.0.0 || ^7.0.0", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "bin": { @@ -5823,12 +5054,15 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.18", - "@vitest/browser-preview": "4.0.18", - "@vitest/browser-webdriverio": "4.0.18", - "@vitest/ui": "4.0.18", + "@vitest/browser-playwright": "4.1.4", + "@vitest/browser-preview": "4.1.4", + "@vitest/browser-webdriverio": "4.1.4", + "@vitest/coverage-istanbul": "4.1.4", + "@vitest/coverage-v8": "4.1.4", + "@vitest/ui": "4.1.4", "happy-dom": "*", - "jsdom": "*" + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { @@ -5849,6 +5083,12 @@ "@vitest/browser-webdriverio": { "optional": true }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, "@vitest/ui": { "optional": true }, @@ -5857,29 +5097,12 @@ }, "jsdom": { "optional": true + }, + "vite": { + "optional": false } } }, - "node_modules/vitest/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/webpack-virtual-modules": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", - "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", - "dev": true, - "license": "MIT" - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6011,9 +5234,9 @@ } }, "node_modules/zod": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz", - "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/integrations/ai-sdk-provider/package.json b/integrations/ai-sdk-provider/package.json index 82ab73207..c3c7f9840 100644 --- a/integrations/ai-sdk-provider/package.json +++ b/integrations/ai-sdk-provider/package.json @@ -5,17 +5,12 @@ "type": "module", "main": "./dist/index.cjs", "module": "./dist/index.mjs", - "types": "./dist/index.d.cts", + "types": "./dist/index.d.mts", "exports": { ".": { - "import": { - "types": "./dist/index.d.mts", - "default": "./dist/index.mjs" - }, - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - } + "types": "./dist/index.d.mts", + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" } }, "files": [ @@ -29,6 +24,7 @@ "dev": "tsdown --watch", "clean": "rm -rf dist", "test": "vitest run", + "test:genie:live": "RUN_GENIE_LIVE_TEST=1 vitest run tests/genie-live-smoke.test.ts", "test:watch": "vitest", "test:coverage": "vitest run --coverage", "typecheck": "tsc --noEmit", @@ -44,25 +40,55 @@ }, "peerDependencies": { "@ai-sdk/provider": "^3.0.5", - "@ai-sdk/provider-utils": "^4.0.10" + "@ai-sdk/provider-utils": "^4.0.10", + "ai": "^6.0.0" }, "dependencies": { - "zod": "^4.3.5" + "zod": "^4.3.6" }, "devDependencies": { - "@arethetypeswrong/cli": "0.15.4", - "@types/node": "22.19.3", - "@typescript-eslint/eslint-plugin": "7.18.0", - "@typescript-eslint/parser": "7.18.0", - "@vitest/coverage-v8": "4.0.18", - "@vitest/ui": "4.0.18", + "@ai-sdk/provider": "^3.0.5", + "@ai-sdk/provider-utils": "^4.0.10", + "@arethetypeswrong/cli": "0.18.2", + "@types/node": "25.6.0", + "@typescript-eslint/eslint-plugin": "8.58.1", + "@typescript-eslint/parser": "8.58.1", + "@vitest/coverage-v8": "4.1.4", + "@vitest/ui": "4.1.4", + "ai": "^6.0.0", + "dotenv": "^17.4.2", "eslint": "8.57.1", "eslint-config-prettier": "9.1.2", - "msw": "2.12.7", - "prettier": "3.7.4", - "tsdown": "0.9.9", + "msw": "2.13.2", + "prettier": "3.8.2", + "tsdown": "0.21.7", "typescript": "5.9.3", - "vitest": "4.0.18" + "vitest": "4.1.4" + }, + "overrides": { + "ajv": "6.14.0", + "flatted": "3.4.2", + "minimatch@3": { + "brace-expansion": "1.1.14" + }, + "minimatch@9": { + "brace-expansion": "2.0.3" + }, + "micromatch": { + "picomatch": "2.3.2" + }, + "vite": { + "picomatch": "4.0.4" + }, + "tinyglobby": { + "picomatch": "4.0.4" + }, + "unplugin": { + "picomatch": "4.0.4" + }, + "vitest": { + "picomatch": "4.0.4" + } }, "author": { "name": "Databricks", diff --git a/integrations/ai-sdk-provider/src/genie/agent.ts b/integrations/ai-sdk-provider/src/genie/agent.ts new file mode 100644 index 000000000..41090c1ee --- /dev/null +++ b/integrations/ai-sdk-provider/src/genie/agent.ts @@ -0,0 +1,344 @@ +import { + Output, + generateText, + streamText, + type Agent, + type GenerateTextResult, + type ModelMessage, + type StreamTextResult, +} from 'ai' +import type { + LanguageModelV3, + LanguageModelV3FinishReason, + LanguageModelV3StreamPart, +} from '@ai-sdk/provider' +import { + createDatabricksGenieConversationClient, + type DatabricksGenieConversationEvent, + type DatabricksGenieAskResult, + type DatabricksGenieConversationClient, + type DatabricksGeniePollingSettings, + type DatabricksGenieSettings, +} from './conversation-client' + +export interface DatabricksGenieAgentCallOptions extends DatabricksGeniePollingSettings { + conversationId?: string + fetchQueryResult?: boolean + headers?: Record +} + +export type DatabricksGenieAgentResult = GenerateTextResult< + Record, + ReturnType +> & { + genie: DatabricksGenieAskResult +} + +export type DatabricksGenieAgentStreamResult = StreamTextResult< + Record, + ReturnType +> & { + genie: Promise +} + +export interface DatabricksGenieAgent + extends Agent< + DatabricksGenieAgentCallOptions, + Record, + ReturnType + > { + readonly genie: DatabricksGenieConversationClient + generate( + options: Parameters< + Agent< + DatabricksGenieAgentCallOptions, + Record, + ReturnType + >['generate'] + >[0] + ): Promise + stream( + options: Parameters< + Agent< + DatabricksGenieAgentCallOptions, + Record, + ReturnType + >['stream'] + >[0] + ): Promise +} + +function extractLatestUserText(messages: ModelMessage[]): string { + for (let index = messages.length - 1; index >= 0; index -= 1) { + const message = messages[index] + if (message.role !== 'user') { + continue + } + + if (typeof message.content === 'string' && message.content.trim().length > 0) { + return message.content.trim() + } + + if (Array.isArray(message.content)) { + const text = message.content + .filter( + ( + part + ): part is Extract<(typeof message.content)[number], { type: 'text'; text: string }> => + typeof part === 'object' && + part !== null && + 'type' in part && + part.type === 'text' && + 'text' in part && + typeof part.text === 'string' + ) + .map((part) => part.text.trim()) + .filter((part) => part.length > 0) + .join('\n') + + if (text.length > 0) { + return text + } + } + } + + throw new Error('Databricks Genie agent requires at least one user message with text content') +} + +function resolvePromptMessages(prompt?: string | ModelMessage[], messages?: ModelMessage[]): ModelMessage[] { + if (typeof prompt === 'string') { + return [{ role: 'user', content: prompt }] + } + + if (Array.isArray(prompt)) { + return prompt + } + + if (Array.isArray(messages)) { + return messages + } + + throw new Error('Databricks Genie agent requires either prompt or messages') +} + +function resolveAgentText(result: DatabricksGenieAskResult): string { + if (result.text.trim().length > 0) { + return result.text + } + + if (result.sql) { + return 'Genie generated a SQL query for this request.' + } + + return 'Genie completed the request.' +} + +function formatGenieStatus(status: string): string { + return status + .toLowerCase() + .split('_') + .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) + .join(' ') +} + +class DatabricksGenieLanguageModel implements LanguageModelV3 { + readonly specificationVersion = 'v3' + readonly modelId = 'genie-conversation' + readonly supportedUrls: Record = {} + + private geniePromise?: Promise + private streamEventListener?: (event: DatabricksGenieConversationEvent) => void + + constructor( + private readonly helper: DatabricksGenieConversationClient, + private readonly question: string, + private readonly requestOptions: DatabricksGenieAgentCallOptions, + private readonly abortSignal?: AbortSignal + ) {} + + get provider(): string { + return 'databricks' + } + + get result(): Promise { + if (!this.geniePromise) { + this.geniePromise = this.helper.ask(this.question, { + ...this.requestOptions, + abortSignal: this.abortSignal, + }) + } + + return this.geniePromise + } + + prepareStreamingResult(onEvent?: (event: DatabricksGenieConversationEvent) => void) { + this.streamEventListener = onEvent + + if (!this.geniePromise) { + this.geniePromise = (async () => { + let completedResult: DatabricksGenieAskResult | undefined + + for await (const event of this.helper.streamConversation(this.question, { + ...this.requestOptions, + abortSignal: this.abortSignal, + })) { + this.streamEventListener?.(event) + + if (event.type === 'complete') { + completedResult = event.result + } + } + + if (!completedResult) { + throw new Error('Databricks Genie conversation ended without a completed result') + } + + return completedResult + })() + } + + return this.geniePromise + } + + async doGenerate( + _options: Parameters[0] + ): Promise>> { + const genie = await this.result + + return { + content: [{ type: 'text', text: resolveAgentText(genie) }], + finishReason: { raw: 'stop', unified: 'stop' }, + usage: { + inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 }, + outputTokens: { total: 0, text: 0, reasoning: 0 }, + }, + warnings: [], + response: { + body: genie, + }, + } + } + + doStream( + _options: Parameters[0] + ): Promise>> { + let finishReason: LanguageModelV3FinishReason = { raw: 'stop', unified: 'stop' } + const textId = 'genie-text-0' + const reasoningId = 'genie-reasoning-0' + + return Promise.resolve({ + stream: new ReadableStream({ + start: async (controller) => { + controller.enqueue({ type: 'stream-start', warnings: [] }) + controller.enqueue({ type: 'reasoning-start', id: reasoningId }) + + try { + const geniePromise = this.prepareStreamingResult((event) => { + if (event.type === 'status') { + controller.enqueue({ + type: 'reasoning-delta', + id: reasoningId, + delta: `${formatGenieStatus(event.status)}\n`, + }) + } + }) + const genie = await geniePromise + + controller.enqueue({ type: 'reasoning-end', id: reasoningId }) + + controller.enqueue({ type: 'text-start', id: textId }) + controller.enqueue({ + type: 'text-delta', + id: textId, + delta: resolveAgentText(genie), + }) + controller.enqueue({ type: 'text-end', id: textId }) + } catch (error) { + finishReason = { raw: 'error', unified: 'error' } + controller.enqueue({ type: 'reasoning-end', id: reasoningId }) + controller.enqueue({ type: 'error', error }) + } finally { + controller.enqueue({ + type: 'finish', + finishReason, + usage: { + inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 }, + outputTokens: { total: 0, text: 0, reasoning: 0 }, + }, + }) + controller.close() + } + }, + }), + request: { + body: { + question: this.question, + }, + }, + response: { + headers: {}, + }, + }) + } +} + +class DefaultDatabricksGenieAgent implements DatabricksGenieAgent { + readonly version = 'agent-v1' as const + readonly tools = {} + readonly genie: DatabricksGenieConversationClient + readonly id: string | undefined + + constructor(settings: DatabricksGenieSettings & { id?: string }) { + this.id = settings.id + this.genie = createDatabricksGenieConversationClient(settings) + } + + async generate({ + prompt, + messages, + options, + abortSignal, + }: Parameters[0]): Promise { + const promptMessages = resolvePromptMessages(prompt, messages) + const question = extractLatestUserText(promptMessages) + const model = new DatabricksGenieLanguageModel(this.genie, question, options ?? {}, abortSignal) + const result = await generateText({ + model, + prompt: question, + abortSignal, + }) + + return Object.assign(result, { + genie: await model.result, + }) as unknown as DatabricksGenieAgentResult + } + + stream({ + prompt, + messages, + options, + abortSignal, + experimental_transform, + }: Parameters[0]): Promise { + const promptMessages = resolvePromptMessages(prompt, messages) + const question = extractLatestUserText(promptMessages) + const model = new DatabricksGenieLanguageModel(this.genie, question, options ?? {}, abortSignal) + const geniePromise = model.prepareStreamingResult() + const result = streamText({ + model, + prompt: question, + abortSignal, + experimental_transform, + }) + + return Promise.resolve(Object.assign(result, { + genie: geniePromise, + }) as unknown as DatabricksGenieAgentStreamResult) + } +} + +export function createDatabricksGenieAgent( + settings: DatabricksGenieSettings & { id?: string } +): DatabricksGenieAgent { + return new DefaultDatabricksGenieAgent(settings) +} diff --git a/integrations/ai-sdk-provider/src/genie/attachment-ordering.ts b/integrations/ai-sdk-provider/src/genie/attachment-ordering.ts new file mode 100644 index 000000000..045a34fc3 --- /dev/null +++ b/integrations/ai-sdk-provider/src/genie/attachment-ordering.ts @@ -0,0 +1,100 @@ +import type { DatabricksGenieNormalizedAttachment } from './types' + +const FOLLOW_UP_QUESTION_PREFIXES = [ + /^would you like\b/i, + /^would you also like\b/i, + /^do you want\b/i, + /^do you also want\b/i, + /^should i\b/i, + /^shall i\b/i, + /^want me to\b/i, + /^would it help if\b/i, +] as const + +export interface DatabricksGenieOrderedAttachments { + answerTextAttachments: DatabricksGenieNormalizedAttachment[] + followUpQuestionAttachments: DatabricksGenieNormalizedAttachment[] + orderedAttachments: DatabricksGenieNormalizedAttachment[] + queryAttachments: DatabricksGenieNormalizedAttachment[] + suggestedQuestionAttachments: DatabricksGenieNormalizedAttachment[] +} + +function getTextContent(attachment: DatabricksGenieNormalizedAttachment): string { + return attachment.type === 'text' ? attachment.text?.content?.trim() ?? '' : '' +} + +function isQuestionText(text: string): boolean { + return text.endsWith('?') +} + +function matchesFollowUpPrefix(text: string): boolean { + return FOLLOW_UP_QUESTION_PREFIXES.some((pattern) => pattern.test(text)) +} + +export function isLikelyDatabricksGenieFollowUpQuestionText(text: string): boolean { + const normalizedText = text.trim() + + if (!normalizedText || !isQuestionText(normalizedText)) { + return false + } + + return matchesFollowUpPrefix(normalizedText) +} + +export function isLikelyDatabricksGenieFollowUpQuestionAttachment( + attachment: DatabricksGenieNormalizedAttachment +): boolean { + if (attachment.type !== 'text') { + return false + } + + if (attachment.text?.purpose === 'FOLLOW_UP_QUESTION') { + return true + } + + const content = getTextContent(attachment) + + return isLikelyDatabricksGenieFollowUpQuestionText(content) +} + +export function orderDatabricksGenieAttachments( + attachments: DatabricksGenieNormalizedAttachment[] +): DatabricksGenieOrderedAttachments { + const answerTextAttachments: DatabricksGenieNormalizedAttachment[] = [] + const followUpQuestionAttachments: DatabricksGenieNormalizedAttachment[] = [] + const queryAttachments: DatabricksGenieNormalizedAttachment[] = [] + const suggestedQuestionAttachments: DatabricksGenieNormalizedAttachment[] = [] + + for (const attachment of attachments) { + if (attachment.type === 'query') { + queryAttachments.push(attachment) + continue + } + + if (attachment.type === 'suggested_questions') { + suggestedQuestionAttachments.push(attachment) + continue + } + + if (attachment.type === 'text') { + if (isLikelyDatabricksGenieFollowUpQuestionAttachment(attachment)) { + followUpQuestionAttachments.push(attachment) + } else { + answerTextAttachments.push(attachment) + } + } + } + + return { + answerTextAttachments, + followUpQuestionAttachments, + orderedAttachments: [ + ...answerTextAttachments, + ...queryAttachments, + ...followUpQuestionAttachments, + ...suggestedQuestionAttachments, + ], + queryAttachments, + suggestedQuestionAttachments, + } +} diff --git a/integrations/ai-sdk-provider/src/genie/client.ts b/integrations/ai-sdk-provider/src/genie/client.ts new file mode 100644 index 000000000..d97fd6cb2 --- /dev/null +++ b/integrations/ai-sdk-provider/src/genie/client.ts @@ -0,0 +1,492 @@ +import type { FetchFunction } from '@ai-sdk/provider-utils' +import { + type DatabricksGenieCreateConversationMessageRequest, + type DatabricksGenieDeleteConversationRequest, + type DatabricksGenieExecuteMessageAttachmentQueryRequest, + type DatabricksGenieGenerateDownloadFullQueryResultRequest, + type DatabricksGenieGenerateDownloadFullQueryResultResponse, + type DatabricksGenieGetConversationMessageRequest, + type DatabricksGenieGetDownloadFullQueryResultRequest, + type DatabricksGenieGetDownloadFullQueryResultResponse, + type DatabricksGenieGetMessageAttachmentQueryResultRequest, + type DatabricksGenieGetQueryResultByAttachmentRequest, + type DatabricksGenieGetSpaceRequest, + type DatabricksGenieListConversationMessagesRequest, + type DatabricksGenieListConversationMessagesResponse, + type DatabricksGenieListConversationsRequest, + type DatabricksGenieListConversationsResponse, + type DatabricksGenieMessage, + type DatabricksGenieQueryResult, + type DatabricksGenieSpace, + type DatabricksGenieStartConversationRequest, + type DatabricksGenieStartConversationResponse, +} from './types' +import { + ensureOkResponse, + getGenieHeaders, + logGenieDebugEvent, + parseJsonResponse, + sanitizeGenieHeaders, + type DatabricksGenieResolvedSettings, +} from './shared' +import { + parseGenerateDownloadFullQueryResultResponse, + parseGetDownloadFullQueryResultResponse, + parseListConversationMessagesResponse, + parseListConversationsResponse, + parseMessage, + parseQueryResult, + parseSpace, + parseStartConversationResponse, +} from './parser' + +export interface DatabricksGenieRequestOptions { + headers?: Record + abortSignal?: AbortSignal +} + +type DatabricksGenieQueryValue = string | number | boolean | undefined + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null +} + +function isParsedGenieMessage(value: unknown): value is DatabricksGenieMessage { + return ( + isRecord(value) && + typeof value.messageId === 'string' && + typeof value.conversationId === 'string' && + Array.isArray(value.normalizedAttachments) && + Array.isArray(value.attachments) + ) +} + +function collectTextAttachmentDebugMetadata(parsed: unknown): unknown[] { + const messages = collectMessagesFromParsedValue(parsed) + + return messages.flatMap((message) => + message.normalizedAttachments + .filter((attachment) => attachment.type === 'text') + .map((attachment) => ({ + messageId: message.messageId, + conversationId: message.conversationId, + attachmentId: attachment.attachmentId, + normalizedText: { + id: attachment.text?.id, + content: attachment.text?.content, + purpose: attachment.text?.purpose, + }, + rawAttachmentKeys: Object.keys(attachment.raw), + rawTextKeys: attachment.text?.raw ? Object.keys(attachment.text.raw) : [], + rawAttachment: attachment.raw, + rawText: attachment.text?.raw, + })) + ) +} + +function collectMessagesFromParsedValue(parsed: unknown): DatabricksGenieMessage[] { + if (!isRecord(parsed)) { + return [] + } + + if (Array.isArray(parsed.messages)) { + return parsed.messages.filter(isParsedGenieMessage) + } + + if (isParsedGenieMessage(parsed.message)) { + return [parsed.message] + } + + if (isParsedGenieMessage(parsed)) { + return [parsed] + } + + return [] +} + +function buildUrl( + settings: DatabricksGenieResolvedSettings, + path: string, + query?: Record +): string { + const url = new URL(settings.url(path)) + + if (query) { + for (const [key, value] of Object.entries(query)) { + if (value === undefined) { + continue + } + + url.searchParams.set(key, String(value)) + } + } + + return url.toString() +} + +async function performJsonRequest({ + settings, + fetch, + url, + method, + headers, + body, + abortSignal, +}: { + settings: DatabricksGenieResolvedSettings + fetch: FetchFunction + url: string + method: string + headers: Record + body?: unknown + abortSignal?: AbortSignal +}): Promise { + logGenieDebugEvent(settings, { + phase: 'request', + method, + url, + headers: sanitizeGenieHeaders(headers), + body: settings.debug.logBodies ? body : undefined, + }) + + const response = await fetch(url, { + method, + headers, + body: body === undefined ? undefined : JSON.stringify(body), + signal: abortSignal, + }) + + let responseBody: unknown + if (settings.debug.logBodies) { + try { + responseBody = await response.clone().json() + } catch { + try { + responseBody = await response.clone().text() + } catch { + responseBody = undefined + } + } + } + + logGenieDebugEvent(settings, { + phase: 'response', + method, + url, + status: response.status, + statusText: response.statusText, + body: responseBody, + }) + + return parseJsonResponse(response) +} + +async function performRequest({ + settings, + fetch, + url, + method, + headers, + body, + abortSignal, +}: { + settings: DatabricksGenieResolvedSettings + fetch: FetchFunction + url: string + method: string + headers: Record + body?: unknown + abortSignal?: AbortSignal +}): Promise { + logGenieDebugEvent(settings, { + phase: 'request', + method, + url, + headers: sanitizeGenieHeaders(headers), + body: settings.debug.logBodies ? body : undefined, + }) + + const response = await fetch(url, { + method, + headers, + body: body === undefined ? undefined : JSON.stringify(body), + signal: abortSignal, + }) + + let responseBody: unknown + if (settings.debug.logBodies) { + try { + responseBody = await response.clone().json() + } catch { + try { + responseBody = await response.clone().text() + } catch { + responseBody = undefined + } + } + } + + logGenieDebugEvent(settings, { + phase: 'response', + method, + url, + status: response.status, + statusText: response.statusText, + body: responseBody, + }) + + await ensureOkResponse(response) +} + +export class DatabricksGenieApiClient { + private static readonly GENIE_SPACES_API_PREFIX = '/api/2.0/genie/spaces' + + constructor(private readonly settings: DatabricksGenieResolvedSettings) {} + + private spacePath(suffix = ''): string { + return `${DatabricksGenieApiClient.GENIE_SPACES_API_PREFIX}/${this.settings.spaceId}${suffix}` + } + + private conversationPath(conversationId: string, suffix = ''): string { + return this.spacePath(`/conversations/${conversationId}${suffix}`) + } + + private messagePath(conversationId: string, messageId: string, suffix = ''): string { + return this.conversationPath(conversationId, `/messages/${messageId}${suffix}`) + } + + private attachmentPath( + conversationId: string, + messageId: string, + attachmentId: string, + suffix = '' + ): string { + return this.messagePath( + conversationId, + messageId, + `/attachments/${attachmentId}${suffix}` + ) + } + + private async requestJson({ + method, + path, + parse, + options = {}, + query, + body, + }: { + method: string + path: string + parse: (value: unknown) => T + options?: DatabricksGenieRequestOptions + query?: Record + body?: unknown + }): Promise { + const response = await performJsonRequest({ + settings: this.settings, + fetch: this.settings.fetch, + url: buildUrl(this.settings, path, query), + method, + headers: getGenieHeaders(this.settings, options.headers), + body, + abortSignal: options.abortSignal, + }) + + const parsed = parse(response) + const textAttachmentMetadata = collectTextAttachmentDebugMetadata(parsed) + + if (textAttachmentMetadata.length > 0) { + logGenieDebugEvent(this.settings, { + phase: 'response', + method, + url: buildUrl(this.settings, path, query), + status: 200, + statusText: 'Parsed Text Attachments', + metadata: { + textAttachments: textAttachmentMetadata, + }, + }) + } + + return parsed + } + + async getSpace( + request: DatabricksGenieGetSpaceRequest = {}, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.requestJson({ + method: 'GET', + path: this.spacePath(), + query: { + include_serialized_space: request.includeSerializedSpace, + }, + options, + parse: parseSpace, + }) + } + + async startConversation( + request: DatabricksGenieStartConversationRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.requestJson({ + method: 'POST', + path: this.spacePath('/start-conversation'), + body: request, + options, + parse: parseStartConversationResponse, + }) + } + + async createMessage( + request: DatabricksGenieCreateConversationMessageRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.requestJson({ + method: 'POST', + path: this.conversationPath(request.conversationId, '/messages'), + body: { content: request.content }, + options, + parse: parseMessage, + }) + } + + async getMessage( + request: DatabricksGenieGetConversationMessageRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.requestJson({ + method: 'GET', + path: this.messagePath(request.conversationId, request.messageId), + options, + parse: parseMessage, + }) + } + + async listConversationMessages( + request: DatabricksGenieListConversationMessagesRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.requestJson({ + method: 'GET', + path: this.conversationPath(request.conversationId, '/messages'), + query: { + page_size: request.pageSize, + page_token: request.pageToken, + }, + options, + parse: parseListConversationMessagesResponse, + }) + } + + async listConversations( + request: DatabricksGenieListConversationsRequest = {}, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.requestJson({ + method: 'GET', + path: this.spacePath('/conversations'), + query: { + include_all: request.includeAll, + page_size: request.pageSize, + page_token: request.pageToken, + }, + options, + parse: parseListConversationsResponse, + }) + } + + async deleteConversation( + request: DatabricksGenieDeleteConversationRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + await performRequest({ + settings: this.settings, + fetch: this.settings.fetch, + url: buildUrl(this.settings, this.conversationPath(request.conversationId)), + method: 'DELETE', + headers: getGenieHeaders(this.settings, options.headers), + abortSignal: options.abortSignal, + }) + } + + async getMessageAttachmentQueryResult( + request: DatabricksGenieGetMessageAttachmentQueryResultRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.requestJson({ + method: 'GET', + path: this.attachmentPath( + request.conversationId, + request.messageId, + request.attachmentId, + '/query-result' + ), + options, + parse: parseQueryResult, + }) + } + + async getQueryResultByAttachment( + request: DatabricksGenieGetQueryResultByAttachmentRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.getMessageAttachmentQueryResult(request, options) + } + + async executeMessageAttachmentQuery( + request: DatabricksGenieExecuteMessageAttachmentQueryRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.requestJson({ + method: 'POST', + path: this.attachmentPath( + request.conversationId, + request.messageId, + request.attachmentId, + '/execute-query' + ), + options, + parse: parseQueryResult, + }) + } + + async generateDownloadFullQueryResult( + request: DatabricksGenieGenerateDownloadFullQueryResultRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.requestJson({ + method: 'POST', + path: this.attachmentPath( + request.conversationId, + request.messageId, + request.attachmentId, + '/downloads' + ), + options, + parse: parseGenerateDownloadFullQueryResultResponse, + }) + } + + async getDownloadFullQueryResult( + request: DatabricksGenieGetDownloadFullQueryResultRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.requestJson({ + method: 'GET', + path: this.attachmentPath( + request.conversationId, + request.messageId, + request.attachmentId, + `/downloads/${request.downloadId}` + ), + query: { + download_id_signature: request.downloadIdSignature, + }, + options, + parse: parseGetDownloadFullQueryResultResponse, + }) + } +} diff --git a/integrations/ai-sdk-provider/src/genie/conversation-client.ts b/integrations/ai-sdk-provider/src/genie/conversation-client.ts new file mode 100644 index 000000000..e9f9672a4 --- /dev/null +++ b/integrations/ai-sdk-provider/src/genie/conversation-client.ts @@ -0,0 +1,862 @@ +import { DatabricksGenieApiClient, type DatabricksGenieRequestOptions } from './client' +import { + orderDatabricksGenieAttachments, +} from './attachment-ordering' +import { + DATABRICKS_GENIE_TERMINAL_MESSAGE_STATUSES, + type DatabricksGenieAttachment, + type DatabricksGenieCreateConversationMessageRequest, + type DatabricksGenieDeleteConversationRequest, + type DatabricksGenieDownloadQueryResultRequest, + type DatabricksGenieDownloadQueryResultResponse, + type DatabricksGenieExecuteMessageAttachmentQueryRequest, + type DatabricksGenieGenerateDownloadFullQueryResultRequest, + type DatabricksGenieGenerateDownloadFullQueryResultResponse, + type DatabricksGenieGetConversationMessageRequest, + type DatabricksGenieGetDownloadFullQueryResultRequest, + type DatabricksGenieGetDownloadFullQueryResultResponse, + type DatabricksGenieGetMessageAttachmentQueryResultRequest, + type DatabricksGenieGetQueryResultByAttachmentRequest, + type DatabricksGenieGetSpaceRequest, + type DatabricksGenieListConversationMessagesRequest, + type DatabricksGenieListConversationMessagesResponse, + type DatabricksGenieListConversationsRequest, + type DatabricksGenieListConversationsResponse, + type DatabricksGenieMessage, + type DatabricksGenieMessageStatus, + type DatabricksGenieNormalizedAttachment, + type DatabricksGenieQueryResult, + type DatabricksGenieSampleQuestion, + type DatabricksGenieSpace, + type DatabricksGenieStartConversationRequest, + type DatabricksGenieStartConversationResponse, +} from './types' +import { + DEFAULT_GENIE_POLLING_SETTINGS, + type DatabricksGeniePollingSettings, + type DatabricksGenieResolvedSettings, + type DatabricksGenieSettings, + resolveDatabricksGenieSettings, + sleep, +} from './shared' + +export interface DatabricksGenieAskOptions extends DatabricksGeniePollingSettings { + conversationId?: string + fetchQueryResult?: boolean + headers?: Record + abortSignal?: AbortSignal + onProgress?: (message: DatabricksGenieMessage) => void +} + +export interface DatabricksGenieAskResult { + attachmentEntries: DatabricksGenieAttachment[] + attachmentId?: string + attachments: DatabricksGenieNormalizedAttachment[] + conversationId: string + message: DatabricksGenieMessage + messageId: string + queryResult?: DatabricksGenieQueryResult + sql?: string + status: DatabricksGenieMessageStatus + suggestedQuestions: string[] + text: string +} + +export interface DatabricksGenieConversationEventBase { + conversationId: string + message: DatabricksGenieMessage + messageId: string +} + +export interface DatabricksGenieStatusEvent extends DatabricksGenieConversationEventBase { + status: DatabricksGenieMessageStatus + type: 'status' +} + +export interface DatabricksGenieAttachmentEvent extends DatabricksGenieConversationEventBase { + attachment: DatabricksGenieNormalizedAttachment + type: 'attachment' +} + +export interface DatabricksGenieQueryResultEvent extends DatabricksGenieConversationEventBase { + attachmentId: string + queryResult: DatabricksGenieQueryResult + type: 'query-result' +} + +export interface DatabricksGenieCompleteEvent extends DatabricksGenieConversationEventBase { + result: DatabricksGenieAskResult + type: 'complete' +} + +export type DatabricksGenieConversationEvent = + | DatabricksGenieStatusEvent + | DatabricksGenieAttachmentEvent + | DatabricksGenieQueryResultEvent + | DatabricksGenieCompleteEvent + +export interface DatabricksGenieConversationClient { + getSpace( + request?: DatabricksGenieGetSpaceRequest | DatabricksGenieRequestOptions, + options?: DatabricksGenieRequestOptions + ): Promise + getSampleQuestions(options?: DatabricksGenieRequestOptions): Promise + startConversation( + question: string, + options?: DatabricksGenieRequestOptions + ): Promise + createMessage( + conversationId: string, + question: string, + options?: DatabricksGenieRequestOptions + ): Promise + getMessage( + conversationId: string, + messageId: string, + options?: DatabricksGenieRequestOptions + ): Promise + listConversationMessages( + request: DatabricksGenieListConversationMessagesRequest, + options?: DatabricksGenieRequestOptions + ): Promise + listConversations( + request?: DatabricksGenieListConversationsRequest, + options?: DatabricksGenieRequestOptions + ): Promise + deleteConversation( + conversationId: string, + options?: DatabricksGenieRequestOptions + ): Promise + waitForCompletion( + conversationId: string, + messageId: string, + options?: DatabricksGenieAskOptions + ): Promise + getQueryResult( + conversationId: string, + messageId: string, + attachmentId: string, + options?: DatabricksGenieRequestOptions + ): Promise + getQueryResultByAttachment( + request: DatabricksGenieGetQueryResultByAttachmentRequest, + options?: DatabricksGenieRequestOptions + ): Promise + executeQueryAttachment( + request: DatabricksGenieExecuteMessageAttachmentQueryRequest, + options?: DatabricksGenieRequestOptions + ): Promise + refreshQueryAttachment( + request: DatabricksGenieExecuteMessageAttachmentQueryRequest, + options?: DatabricksGenieAskOptions + ): Promise + generateDownloadFullQueryResult( + request: DatabricksGenieGenerateDownloadFullQueryResultRequest, + options?: DatabricksGenieRequestOptions + ): Promise + getDownloadFullQueryResult( + request: DatabricksGenieGetDownloadFullQueryResultRequest, + options?: DatabricksGenieRequestOptions + ): Promise + downloadQueryResult( + request: DatabricksGenieDownloadQueryResultRequest, + options?: DatabricksGenieAskOptions + ): Promise + streamConversation( + question: string, + options?: DatabricksGenieAskOptions + ): AsyncIterable + ask(question: string, options?: DatabricksGenieAskOptions): Promise +} + +function isGenieRequestOptions( + value: DatabricksGenieGetSpaceRequest | DatabricksGenieRequestOptions +): value is DatabricksGenieRequestOptions { + return 'headers' in value || 'abortSignal' in value +} + +function extractAskResult( + message: DatabricksGenieMessage, + queryResult?: DatabricksGenieQueryResult +): DatabricksGenieAskResult { + const orderedAttachments = orderDatabricksGenieAttachments(message.normalizedAttachments) + const textAttachments = orderedAttachments.answerTextAttachments + const queryAttachments = orderedAttachments.queryAttachments + const suggestedQuestionsAttachments = orderedAttachments.suggestedQuestionAttachments + const queryAttachment = queryAttachments[0] + const textSourceAttachments = + textAttachments.length > 0 ? textAttachments : orderedAttachments.followUpQuestionAttachments + const text = textSourceAttachments + .map((attachment) => attachment.text?.content?.trim()) + .filter((value): value is string => typeof value === 'string' && value.length > 0) + .join('\n\n') + const suggestedQuestions = suggestedQuestionsAttachments.flatMap( + (attachment) => attachment.suggestedQuestions?.questions ?? [] + ) + + return { + attachmentEntries: message.attachments, + attachmentId: queryAttachment?.attachmentId, + attachments: orderedAttachments.orderedAttachments, + conversationId: message.conversationId, + message, + messageId: message.messageId, + queryResult, + sql: queryAttachment?.query?.query, + status: message.status, + suggestedQuestions, + text, + } +} + +function getAttachmentEventKey(attachment: DatabricksGenieNormalizedAttachment): string { + switch (attachment.type) { + case 'query': + return JSON.stringify({ + attachmentId: attachment.attachmentId, + description: attachment.query?.description, + parameters: attachment.query?.parameters ?? [], + query: attachment.query?.query, + queryResultMetadata: attachment.query?.queryResultMetadata, + statementId: attachment.query?.statementId, + thoughts: attachment.query?.thoughts ?? [], + title: attachment.query?.title, + type: attachment.type, + }) + case 'suggested_questions': + return JSON.stringify({ + attachmentId: attachment.attachmentId, + questions: attachment.suggestedQuestions?.questions ?? [], + type: attachment.type, + }) + case 'text': + return JSON.stringify({ + attachmentId: attachment.attachmentId, + content: attachment.text?.content, + purpose: attachment.text?.purpose, + type: attachment.type, + }) + default: + return JSON.stringify({ + attachmentId: attachment.attachmentId, + type: attachment.type, + }) + } +} + +function isRetryableQueryResultFetchError(error: unknown): boolean { + if (!(error instanceof Error)) { + return false + } + + return ( + error.message.includes('404') || + error.message.includes('409') || + error.message.includes('425') || + error.message.includes('not ready') || + error.message.includes('not available') + ) +} + +function isSerializedSpaceUnavailableError(error: unknown): boolean { + if (!(error instanceof Error)) { + return false + } + + return ( + error.message.includes('400 Bad Request') && + error.message.includes('Serialized export is not available to integrated Genie spaces') + ) +} + +function isUsableStreamedQueryResult(queryResult: DatabricksGenieQueryResult): boolean { + return ( + queryResult.externalLinks.length > 0 || + queryResult.rows.length > 0 || + queryResult.statementState === 'SUCCEEDED' + ) +} + +class DefaultDatabricksGenieConversationClient implements DatabricksGenieConversationClient { + private readonly client: DatabricksGenieApiClient + private readonly polling: Required + private readonly settings: DatabricksGenieResolvedSettings + + constructor(settings: DatabricksGenieSettings) { + const resolvedSettings = resolveDatabricksGenieSettings(settings) + this.settings = resolvedSettings + this.client = new DatabricksGenieApiClient(resolvedSettings) + this.polling = resolvedSettings.polling + } + + private getPollingSettings(options: DatabricksGenieAskOptions = {}) { + return { + timeoutMs: options.timeoutMs ?? this.polling.timeoutMs, + initialPollIntervalMs: + options.initialPollIntervalMs ?? this.polling.initialPollIntervalMs, + maxPollIntervalMs: options.maxPollIntervalMs ?? this.polling.maxPollIntervalMs, + backoffMultiplier: options.backoffMultiplier ?? this.polling.backoffMultiplier, + } + } + + private async fetchExternalQueryResultLink( + url: string, + headers: Record, + options: DatabricksGenieRequestOptions + ): Promise { + const response = await this.settings.fetch(url, { + method: 'GET', + headers, + signal: options.abortSignal, + }) + + if (!response.ok) { + let body = '' + try { + body = await response.text() + } catch { + // Ignore body parsing errors here and rely on status text. + } + + throw new Error( + `Databricks Genie external result download failed with ${response.status} ${response.statusText}${ + body ? `: ${body}` : '' + }` + ) + } + + return response.text() + } + + private formatQueryResultAsCsv(queryResult: DatabricksGenieQueryResult): string { + const rows = [ + queryResult.columns.map((column) => column.name), + ...queryResult.rows.map((row) => + row.map((cell) => { + if (cell == null) { + return '' + } + + return typeof cell === 'string' ? cell : JSON.stringify(cell) + }) + ), + ] + + return rows + .map((row) => + row + .map((cell) => { + const normalizedCell = String(cell) + const escapedCell = normalizedCell.replace(/"/g, '""') + return /[",\n\r]/.test(escapedCell) ? `"${escapedCell}"` : escapedCell + }) + .join(',') + ) + .join('\n') + } + + async getSpace( + requestOrOptions: DatabricksGenieGetSpaceRequest | DatabricksGenieRequestOptions = {}, + options: DatabricksGenieRequestOptions = {} + ): Promise { + const request: DatabricksGenieGetSpaceRequest = isGenieRequestOptions(requestOrOptions) + ? { includeSerializedSpace: true } + : requestOrOptions + const requestOptions = isGenieRequestOptions(requestOrOptions) ? requestOrOptions : options + + return this.client.getSpace( + { + includeSerializedSpace: request.includeSerializedSpace ?? true, + }, + requestOptions + ) + } + + async getSampleQuestions( + options: DatabricksGenieRequestOptions = {} + ): Promise { + try { + const space = await this.getSpace({ includeSerializedSpace: true }, options) + return space.serializedSpace?.sampleQuestions ?? [] + } catch (error) { + if (isSerializedSpaceUnavailableError(error)) { + return [] + } + + throw error + } + } + + async startConversation( + question: string, + options: DatabricksGenieRequestOptions = {} + ): Promise { + const request: DatabricksGenieStartConversationRequest = { content: question } + return this.client.startConversation(request, options) + } + + async createMessage( + conversationId: string, + question: string, + options: DatabricksGenieRequestOptions = {} + ): Promise { + const request: DatabricksGenieCreateConversationMessageRequest = { + content: question, + conversationId, + } + + return this.client.createMessage(request, options) + } + + async getMessage( + conversationId: string, + messageId: string, + options: DatabricksGenieRequestOptions = {} + ): Promise { + const request: DatabricksGenieGetConversationMessageRequest = { + conversationId, + messageId, + } + + return this.client.getMessage(request, options) + } + + async listConversationMessages( + request: DatabricksGenieListConversationMessagesRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.client.listConversationMessages(request, options) + } + + async listConversations( + request: DatabricksGenieListConversationsRequest = {}, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.client.listConversations(request, options) + } + + async deleteConversation( + conversationId: string, + options: DatabricksGenieRequestOptions = {} + ): Promise { + const request: DatabricksGenieDeleteConversationRequest = { + conversationId, + } + + await this.client.deleteConversation(request, options) + } + + async waitForCompletion( + conversationId: string, + messageId: string, + options: DatabricksGenieAskOptions = {} + ): Promise { + const { timeoutMs, initialPollIntervalMs, maxPollIntervalMs, backoffMultiplier } = + this.getPollingSettings(options) + + let pollIntervalMs = initialPollIntervalMs + const startedAt = Date.now() + let lastStatus: DatabricksGenieMessageStatus | undefined + + for (;;) { + if (Date.now() - startedAt >= timeoutMs) { + throw new Error( + `Databricks Genie polling timed out after ${Math.floor(timeoutMs / 1000)}s${ + lastStatus ? ` (last status: ${lastStatus})` : '' + }` + ) + } + + const message = await this.getMessage(conversationId, messageId, options) + lastStatus = message.status + options.onProgress?.(message) + + if ( + DATABRICKS_GENIE_TERMINAL_MESSAGE_STATUSES.includes( + message.status as (typeof DATABRICKS_GENIE_TERMINAL_MESSAGE_STATUSES)[number] + ) + ) { + if (message.status === 'FAILED') { + throw new Error( + `Databricks Genie message failed: ${message.error?.error ?? 'Unknown error'}${ + message.error?.type ? ` (${message.error.type})` : '' + }` + ) + } + + if (message.status === 'CANCELLED') { + throw new Error('Databricks Genie message was cancelled') + } + + if (message.status === 'QUERY_RESULT_EXPIRED') { + throw new Error('Databricks Genie query result expired') + } + + return message + } + + await sleep(pollIntervalMs, options.abortSignal) + pollIntervalMs = Math.min( + Math.max(pollIntervalMs * backoffMultiplier, initialPollIntervalMs), + maxPollIntervalMs + ) + } + } + + async getQueryResult( + conversationId: string, + messageId: string, + attachmentId: string, + options: DatabricksGenieRequestOptions = {} + ): Promise { + const request: DatabricksGenieGetMessageAttachmentQueryResultRequest = { + attachmentId, + conversationId, + messageId, + } + + return this.client.getMessageAttachmentQueryResult(request, options) + } + + async getQueryResultByAttachment( + request: DatabricksGenieGetQueryResultByAttachmentRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.client.getQueryResultByAttachment(request, options) + } + + async executeQueryAttachment( + request: DatabricksGenieExecuteMessageAttachmentQueryRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.client.executeMessageAttachmentQuery(request, options) + } + + async refreshQueryAttachment( + request: DatabricksGenieExecuteMessageAttachmentQueryRequest, + options: DatabricksGenieAskOptions = {} + ): Promise { + const { timeoutMs, initialPollIntervalMs, maxPollIntervalMs, backoffMultiplier } = + this.getPollingSettings(options) + const startedAt = Date.now() + let pollIntervalMs = initialPollIntervalMs + + let queryResult = await this.executeQueryAttachment(request, options) + + for (;;) { + const statementState = queryResult.statementState + + if ( + queryResult.rows.length > 0 || + queryResult.externalLinks.length > 0 || + statementState === 'SUCCEEDED' + ) { + return queryResult + } + + if ( + statementState === 'FAILED' || + statementState === 'CANCELED' || + statementState === 'CLOSED' + ) { + throw new Error( + `Databricks Genie refreshed query result is not available (statement state: ${statementState})` + ) + } + + if (Date.now() - startedAt >= timeoutMs) { + throw new Error( + `Databricks Genie refreshed query result timed out after ${Math.floor( + timeoutMs / 1000 + )}s` + ) + } + + await sleep(pollIntervalMs, options.abortSignal) + pollIntervalMs = Math.min( + Math.max(pollIntervalMs * backoffMultiplier, initialPollIntervalMs), + maxPollIntervalMs + ) + + queryResult = await this.getQueryResult( + request.conversationId, + request.messageId, + request.attachmentId, + options + ) + } + } + + async generateDownloadFullQueryResult( + request: DatabricksGenieGenerateDownloadFullQueryResultRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.client.generateDownloadFullQueryResult(request, options) + } + + async getDownloadFullQueryResult( + request: DatabricksGenieGetDownloadFullQueryResultRequest, + options: DatabricksGenieRequestOptions = {} + ): Promise { + return this.client.getDownloadFullQueryResult(request, options) + } + + async downloadQueryResult( + request: DatabricksGenieDownloadQueryResultRequest, + options: DatabricksGenieAskOptions = {} + ): Promise { + const { timeoutMs, initialPollIntervalMs, maxPollIntervalMs, backoffMultiplier } = + this.getPollingSettings(options) + const startedAt = Date.now() + let pollIntervalMs = initialPollIntervalMs + + const download = await this.generateDownloadFullQueryResult(request, options) + + for (;;) { + if (Date.now() - startedAt >= timeoutMs) { + throw new Error( + `Databricks Genie full query result download timed out after ${Math.floor( + timeoutMs / 1000 + )}s` + ) + } + + const response = await this.getDownloadFullQueryResult( + { + ...request, + downloadId: download.downloadId, + downloadIdSignature: download.downloadIdSignature, + }, + options + ) + const queryResult = response.queryResult + const externalLink = queryResult.externalLinks[0] + const statementState = queryResult.statementState + + if (externalLink?.externalLink) { + const content = await this.fetchExternalQueryResultLink( + externalLink.externalLink, + externalLink.httpHeaders ?? {}, + options + ) + + return { + content, + contentType: 'text/csv; charset=utf-8', + fileName: `genie-query-result-${request.attachmentId}.csv`, + queryResult, + } + } + + if (queryResult.rows.length > 0 || statementState === 'SUCCEEDED') { + return { + content: this.formatQueryResultAsCsv(queryResult), + contentType: 'text/csv; charset=utf-8', + fileName: `genie-query-result-${request.attachmentId}.csv`, + queryResult, + } + } + + if ( + statementState === 'FAILED' || + statementState === 'CANCELED' || + statementState === 'CLOSED' + ) { + throw new Error( + `Databricks Genie full query result download is not available (statement state: ${statementState})` + ) + } + + await sleep(pollIntervalMs, options.abortSignal) + pollIntervalMs = Math.min( + Math.max(pollIntervalMs * backoffMultiplier, initialPollIntervalMs), + maxPollIntervalMs + ) + } + } + + async *streamConversation( + question: string, + options: DatabricksGenieAskOptions = {} + ): AsyncIterable { + const initialMessage = options.conversationId + ? await this.createMessage(options.conversationId, question, options) + : await this.startConversation(question, options).then((response) => response.message) + + let lastStatus: DatabricksGenieMessageStatus | undefined + let queryResult: DatabricksGenieQueryResult | undefined + let queryResultAttachmentId: string | undefined + const emittedAttachmentKeys = new Set() + + const emitMessageProgress = async function* ( + client: DefaultDatabricksGenieConversationClient, + message: DatabricksGenieMessage, + shouldFetchQueryResult: boolean, + allowRetryableQueryResultErrors: boolean + ): AsyncIterable { + options.onProgress?.(message) + + if (lastStatus !== message.status) { + lastStatus = message.status + yield { + type: 'status', + conversationId: message.conversationId, + messageId: message.messageId, + message, + status: message.status, + } + } + + for (const attachment of message.normalizedAttachments) { + const attachmentKey = getAttachmentEventKey(attachment) + + if (!emittedAttachmentKeys.has(attachmentKey)) { + emittedAttachmentKeys.add(attachmentKey) + yield { + type: 'attachment', + attachment, + conversationId: message.conversationId, + messageId: message.messageId, + message, + } + } + } + + const queryAttachment = message.normalizedAttachments.find( + (attachment) => attachment.type === 'query' && attachment.attachmentId + ) + + if ( + shouldFetchQueryResult && + queryAttachment?.attachmentId && + queryResultAttachmentId !== queryAttachment.attachmentId + ) { + try { + const nextQueryResult = await client.getQueryResult( + message.conversationId, + message.messageId, + queryAttachment.attachmentId, + options + ) + + if (isUsableStreamedQueryResult(nextQueryResult)) { + queryResult = nextQueryResult + queryResultAttachmentId = queryAttachment.attachmentId + yield { + type: 'query-result', + attachmentId: queryAttachment.attachmentId, + conversationId: message.conversationId, + messageId: message.messageId, + message, + queryResult, + } + } + } catch (error) { + if (!allowRetryableQueryResultErrors || !isRetryableQueryResultFetchError(error)) { + throw error + } + } + } + } + + let currentMessage = initialMessage + yield* emitMessageProgress(this, currentMessage, Boolean(options.fetchQueryResult), true) + + if (!DATABRICKS_GENIE_TERMINAL_MESSAGE_STATUSES.includes(currentMessage.status as never)) { + const timeoutMs = options.timeoutMs ?? this.polling.timeoutMs + const initialPollIntervalMs = + options.initialPollIntervalMs ?? this.polling.initialPollIntervalMs + const maxPollIntervalMs = options.maxPollIntervalMs ?? this.polling.maxPollIntervalMs + const backoffMultiplier = options.backoffMultiplier ?? this.polling.backoffMultiplier + const startedAt = Date.now() + let pollIntervalMs = initialPollIntervalMs + + for (;;) { + if (Date.now() - startedAt >= timeoutMs) { + throw new Error( + `Databricks Genie polling timed out after ${Math.floor(timeoutMs / 1000)}s${ + lastStatus ? ` (last status: ${lastStatus})` : '' + }` + ) + } + + await sleep(pollIntervalMs, options.abortSignal) + currentMessage = await this.getMessage( + initialMessage.conversationId, + initialMessage.messageId, + options + ) + yield* emitMessageProgress(this, currentMessage, Boolean(options.fetchQueryResult), true) + + if ( + DATABRICKS_GENIE_TERMINAL_MESSAGE_STATUSES.includes(currentMessage.status as never) + ) { + break + } + + pollIntervalMs = Math.min( + Math.max(pollIntervalMs * backoffMultiplier, initialPollIntervalMs), + maxPollIntervalMs + ) + } + } + + if (currentMessage.status === 'FAILED') { + throw new Error( + `Databricks Genie message failed: ${currentMessage.error?.error ?? 'Unknown error'}${ + currentMessage.error?.type ? ` (${currentMessage.error.type})` : '' + }` + ) + } + + if (currentMessage.status === 'CANCELLED') { + throw new Error('Databricks Genie message was cancelled') + } + + if (currentMessage.status === 'QUERY_RESULT_EXPIRED') { + throw new Error('Databricks Genie query result expired') + } + + const completedMessage = + currentMessage.status === 'COMPLETED' + ? await this.getMessage(currentMessage.conversationId, currentMessage.messageId, options) + : currentMessage + + yield* emitMessageProgress(this, completedMessage, Boolean(options.fetchQueryResult), false) + + const result = extractAskResult(completedMessage, queryResult) + yield { + type: 'complete', + conversationId: completedMessage.conversationId, + messageId: completedMessage.messageId, + message: completedMessage, + result, + } + } + + async ask(question: string, options: DatabricksGenieAskOptions = {}): Promise { + let completedResult: DatabricksGenieAskResult | undefined + + for await (const event of this.streamConversation(question, options)) { + if (event.type === 'complete') { + completedResult = event.result + } + } + + if (!completedResult) { + throw new Error('Databricks Genie conversation ended without a completed result') + } + + return completedResult + } +} + +export function createDatabricksGenieConversationClient( + settings: DatabricksGenieSettings +): DatabricksGenieConversationClient { + return new DefaultDatabricksGenieConversationClient(settings) +} + +export { DEFAULT_GENIE_POLLING_SETTINGS } +export type { DatabricksGeniePollingSettings, DatabricksGenieSettings } +export * from './types' diff --git a/integrations/ai-sdk-provider/src/genie/index.ts b/integrations/ai-sdk-provider/src/genie/index.ts new file mode 100644 index 000000000..f66ae9cab --- /dev/null +++ b/integrations/ai-sdk-provider/src/genie/index.ts @@ -0,0 +1,3 @@ +export * from './attachment-ordering' +export * from './agent' +export * from './conversation-client' diff --git a/integrations/ai-sdk-provider/src/genie/parser.ts b/integrations/ai-sdk-provider/src/genie/parser.ts new file mode 100644 index 000000000..2fb6366b7 --- /dev/null +++ b/integrations/ai-sdk-provider/src/genie/parser.ts @@ -0,0 +1,520 @@ +import { + type DatabricksGenieAttachment, + type DatabricksGenieConversation, + type DatabricksGenieConversationSummary, + type DatabricksGenieFeedback, + type DatabricksGenieGenerateDownloadFullQueryResultResponse, + type DatabricksGenieGetDownloadFullQueryResultResponse, + type DatabricksGenieListConversationMessagesResponse, + type DatabricksGenieListConversationsResponse, + type DatabricksGenieMessage, + type DatabricksGenieMessageError, + type DatabricksGenieNormalizedAttachment, + type DatabricksGenieQueryAttachment, + type DatabricksGenieQueryAttachmentParameter, + type DatabricksGenieQueryAttachmentThought, + type DatabricksGenieQueryResult, + type DatabricksGenieQueryResultColumn, + type DatabricksGenieQueryResultExternalLink, + type DatabricksGenieResultMetadata, + type DatabricksGenieSampleQuestion, + type DatabricksGenieSerializedSpace, + type DatabricksGenieSpace, + type DatabricksGenieStartConversationResponse, + type DatabricksGenieSuggestedQuestionsAttachment, + type DatabricksGenieTextAttachment, +} from './types' +import { isRecord, isStringArray } from './shared' + +function assertRecord(value: unknown, context: string): Record { + if (!isRecord(value)) { + throw new Error(`Expected ${context} to be an object`) + } + + return value +} + +function getOptionalString(value: unknown): string | undefined { + return typeof value === 'string' ? value : undefined +} + +function getRequiredString(value: unknown, fieldName: string): string { + if (typeof value !== 'string' || value.length === 0) { + throw new Error(`Expected ${fieldName} to be a non-empty string`) + } + + return value +} + +function getOptionalNumber(value: unknown): number | undefined { + return typeof value === 'number' && Number.isFinite(value) ? value : undefined +} + +function getOptionalBoolean(value: unknown): boolean | undefined { + return typeof value === 'boolean' ? value : undefined +} + +function parseQueryAttachmentParameter( + value: unknown +): DatabricksGenieQueryAttachmentParameter | null { + if (!isRecord(value)) { + return null + } + + return { + keyword: getOptionalString(value.keyword), + sqlType: getOptionalString(value.sql_type), + value: getOptionalString(value.value), + raw: value, + } +} + +function parseQueryAttachmentThought( + value: unknown +): DatabricksGenieQueryAttachmentThought | null { + if (!isRecord(value)) { + return null + } + + return { + content: getOptionalString(value.content), + thoughtType: getOptionalString(value.thought_type), + raw: value, + } +} + +function parseQueryResultExternalLink( + value: unknown +): DatabricksGenieQueryResultExternalLink | null { + if (!isRecord(value)) { + return null + } + + const httpHeaders = isRecord(value.http_headers) + ? Object.fromEntries( + Object.entries(value.http_headers).filter( + (entry): entry is [string, string] => typeof entry[1] === 'string' + ) + ) + : undefined + + return { + byteCount: getOptionalNumber(value.byte_count), + chunkIndex: getOptionalNumber(value.chunk_index), + expiration: getOptionalString(value.expiration), + externalLink: getOptionalString(value.external_link), + httpHeaders, + nextChunkIndex: getOptionalNumber(value.next_chunk_index), + nextChunkInternalLink: getOptionalString(value.next_chunk_internal_link), + rowCount: getOptionalNumber(value.row_count), + rowOffset: getOptionalNumber(value.row_offset), + } +} + +function parseResultMetadata(value: unknown): DatabricksGenieResultMetadata | undefined { + if (!isRecord(value)) { + return undefined + } + + return { + isTruncated: getOptionalBoolean(value.is_truncated), + rowCount: getOptionalNumber(value.row_count), + statementId: getOptionalString(value.statement_id), + statementIdSignature: getOptionalString(value.statement_id_signature), + raw: value, + } +} + +function parseQueryAttachment( + value: unknown, + attachmentId?: string +): DatabricksGenieQueryAttachment | undefined { + if (!isRecord(value)) { + return undefined + } + + return { + attachmentId, + description: getOptionalString(value.description), + id: getOptionalString(value.id), + lastUpdatedTimestamp: getOptionalNumber(value.last_updated_timestamp), + parameters: Array.isArray(value.parameters) + ? value.parameters + .map(parseQueryAttachmentParameter) + .filter((item): item is DatabricksGenieQueryAttachmentParameter => item !== null) + : [], + query: getOptionalString(value.query), + queryResultMetadata: parseResultMetadata(value.query_result_metadata), + statementId: getOptionalString(value.statement_id), + thoughts: Array.isArray(value.thoughts) + ? value.thoughts + .map(parseQueryAttachmentThought) + .filter((item): item is DatabricksGenieQueryAttachmentThought => item !== null) + : [], + title: getOptionalString(value.title), + raw: value, + } +} + +function parseTextAttachment(value: unknown, attachmentId?: string): DatabricksGenieTextAttachment | undefined { + if (!isRecord(value)) { + return undefined + } + + return { + attachmentId, + content: getOptionalString(value.content), + id: getOptionalString(value.id), + purpose: getOptionalString(value.purpose), + raw: value, + } +} + +function parseSuggestedQuestionsAttachment( + value: unknown, + attachmentId?: string +): DatabricksGenieSuggestedQuestionsAttachment | undefined { + if (!isRecord(value)) { + return undefined + } + + return { + attachmentId, + questions: isStringArray(value.questions) ? value.questions : [], + raw: value, + } +} + +function flattenAttachment(attachment: DatabricksGenieAttachment): DatabricksGenieNormalizedAttachment[] { + const normalized: DatabricksGenieNormalizedAttachment[] = [] + + if (attachment.query) { + normalized.push({ + attachmentId: attachment.attachmentId, + type: 'query', + query: attachment.query, + raw: attachment.raw, + }) + } + + if (attachment.text) { + normalized.push({ + attachmentId: attachment.attachmentId, + type: 'text', + text: attachment.text, + raw: attachment.raw, + }) + } + + if (attachment.suggestedQuestions) { + normalized.push({ + attachmentId: attachment.attachmentId, + type: 'suggested_questions', + suggestedQuestions: attachment.suggestedQuestions, + raw: attachment.raw, + }) + } + + return normalized +} + +function parseAttachment(value: unknown): DatabricksGenieAttachment | null { + if (!isRecord(value)) { + return null + } + + const attachmentId = getOptionalString(value.attachment_id) + + return { + attachmentId, + query: parseQueryAttachment(value.query, attachmentId), + suggestedQuestions: parseSuggestedQuestionsAttachment(value.suggested_questions, attachmentId), + text: parseTextAttachment(value.text, attachmentId), + raw: value, + } +} + +function parseMessageError(value: unknown): DatabricksGenieMessageError | undefined { + if (!isRecord(value)) { + return undefined + } + + return { + error: getOptionalString(value.error), + type: getOptionalString(value.type), + raw: value, + } +} + +function parseFeedback(value: unknown): DatabricksGenieFeedback | undefined { + if (!isRecord(value)) { + return undefined + } + + return { + rating: getOptionalString(value.rating), + raw: value, + } +} + +export function parseMessage(value: unknown): DatabricksGenieMessage { + const record = assertRecord(value, 'Databricks Genie message') + const attachments = Array.isArray(record.attachments) + ? record.attachments + .map(parseAttachment) + .filter((item): item is DatabricksGenieAttachment => item !== null) + : [] + const messageId = + getOptionalString(record.message_id) ?? getRequiredString(record.id, 'message.id') + const legacyId = getOptionalString(record.id) + + return { + attachments, + normalizedAttachments: attachments.flatMap(flattenAttachment), + content: getOptionalString(record.content), + conversationId: getRequiredString(record.conversation_id, 'message.conversation_id'), + createdTimestamp: getOptionalNumber(record.created_timestamp), + error: parseMessageError(record.error), + feedback: parseFeedback(record.feedback), + id: messageId, + lastUpdatedTimestamp: getOptionalNumber(record.last_updated_timestamp), + legacyId, + messageId, + queryResult: parseResultMetadata(record.query_result), + spaceId: getOptionalString(record.space_id), + status: getRequiredString(record.status, 'message.status'), + userId: getOptionalNumber(record.user_id), + raw: record, + } +} + +export function parseConversation(value: unknown): DatabricksGenieConversation { + const record = assertRecord(value, 'Databricks Genie conversation') + const conversationId = + getOptionalString(record.conversation_id) ?? getRequiredString(record.id, 'conversation.id') + const legacyId = getOptionalString(record.id) + + return { + conversationId, + createdTimestamp: getOptionalNumber(record.created_timestamp), + id: conversationId, + lastUpdatedTimestamp: getOptionalNumber(record.last_updated_timestamp), + legacyId, + spaceId: getOptionalString(record.space_id), + title: getOptionalString(record.title), + userId: getOptionalNumber(record.user_id), + raw: record, + } +} + +export function parseConversationSummary(value: unknown): DatabricksGenieConversationSummary { + const record = assertRecord(value, 'Databricks Genie conversation summary') + + return { + conversationId: getRequiredString(record.conversation_id, 'conversation_summary.conversation_id'), + createdTimestamp: getOptionalNumber(record.created_timestamp), + title: getOptionalString(record.title), + raw: record, + } +} + +function parseSerializedSpaceSampleQuestion(value: unknown): DatabricksGenieSampleQuestion | null { + if (!isRecord(value)) { + return null + } + + const question = Array.isArray(value.question) + ? value.question.filter((item): item is string => typeof item === 'string' && item.trim().length > 0) + : [] + + if (question.length === 0) { + return null + } + + return { + id: getOptionalString(value.id), + text: question.join(' ').trim(), + raw: value, + } +} + +function parseSerializedSpace(value: unknown): DatabricksGenieSerializedSpace | undefined { + if (typeof value !== 'string' || value.trim().length === 0) { + return undefined + } + + let parsed: unknown + try { + parsed = JSON.parse(value) + } catch (error) { + throw new Error( + `Failed to parse Databricks Genie serialized_space: ${ + error instanceof Error ? error.message : String(error) + }` + ) + } + + const record = assertRecord(parsed, 'Databricks Genie serialized_space') + const config = isRecord(record.config) ? record.config : {} + const sampleQuestions = Array.isArray(config.sample_questions) + ? config.sample_questions + .map(parseSerializedSpaceSampleQuestion) + .filter((item): item is DatabricksGenieSampleQuestion => item !== null) + : [] + + return { + sampleQuestions, + raw: record, + } +} + +export function parseSpace(value: unknown): DatabricksGenieSpace { + const record = assertRecord(value, 'Databricks Genie space') + const spaceId = + getOptionalString(record.space_id) ?? getRequiredString(record.id, 'space.space_id') + + return { + description: getOptionalString(record.description), + id: spaceId, + parentPath: getOptionalString(record.parent_path), + serializedSpace: parseSerializedSpace(record.serialized_space), + serializedSpaceText: getOptionalString(record.serialized_space), + spaceId, + title: getOptionalString(record.title), + warehouseId: getOptionalString(record.warehouse_id), + raw: record, + } +} + +export function parseStartConversationResponse(value: unknown): DatabricksGenieStartConversationResponse { + const record = assertRecord(value, 'Databricks Genie start conversation response') + const conversation = parseConversation(record.conversation) + const message = parseMessage(record.message) + + return { + conversation, + conversationId: + getOptionalString(record.conversation_id) ?? conversation.conversationId, + message, + messageId: getOptionalString(record.message_id) ?? message.messageId, + raw: record, + } +} + +export function parseListConversationMessagesResponse( + value: unknown +): DatabricksGenieListConversationMessagesResponse { + const record = assertRecord(value, 'Databricks Genie list conversation messages response') + + return { + messages: Array.isArray(record.messages) ? record.messages.map(parseMessage) : [], + nextPageToken: getOptionalString(record.next_page_token), + raw: record, + } +} + +export function parseListConversationsResponse( + value: unknown +): DatabricksGenieListConversationsResponse { + const record = assertRecord(value, 'Databricks Genie list conversations response') + + return { + conversations: Array.isArray(record.conversations) + ? record.conversations.map(parseConversationSummary) + : [], + nextPageToken: getOptionalString(record.next_page_token), + raw: record, + } +} + +export function parseQueryResult(value: unknown): DatabricksGenieQueryResult { + const record = assertRecord(value, 'Databricks Genie query result response') + const statementResponse = isRecord(record.statement_response) + ? record.statement_response + : undefined + const manifest = statementResponse && isRecord(statementResponse.manifest) + ? statementResponse.manifest + : undefined + const schema = manifest && isRecord(manifest.schema) ? manifest.schema : undefined + const columnsValue = schema && Array.isArray(schema.columns) ? schema.columns : [] + const resultValue = statementResponse && isRecord(statementResponse.result) + ? statementResponse.result + : undefined + const rowsValue = resultValue && Array.isArray(resultValue.data_array) ? resultValue.data_array : [] + const externalLinksValue = + resultValue && Array.isArray(resultValue.external_links) ? resultValue.external_links : [] + const rowCount = + getOptionalNumber(record.row_count) ?? + getOptionalNumber(resultValue?.row_count) ?? + getOptionalNumber(manifest?.total_row_count) ?? + rowsValue.length + const truncated = + getOptionalBoolean(record.is_truncated) ?? + getOptionalBoolean(manifest?.truncated) ?? + rowCount > rowsValue.length + + return { + columns: columnsValue.reduce((result, column) => { + if (!isRecord(column) || typeof column.name !== "string") { + return result + } + + result.push({ + name: column.name, + typeName: getOptionalString(column.type_name), + }) + + return result + }, []), + byteCount: getOptionalNumber(resultValue?.byte_count), + chunkIndex: getOptionalNumber(resultValue?.chunk_index), + externalLinks: externalLinksValue.reduce( + (result, link) => { + const parsedLink = parseQueryResultExternalLink(link) + + if (parsedLink) { + result.push(parsedLink) + } + + return result + }, + [] + ), + nextChunkIndex: getOptionalNumber(resultValue?.next_chunk_index), + nextChunkInternalLink: getOptionalString(resultValue?.next_chunk_internal_link), + rows: rowsValue.filter((row): row is unknown[][][number] => Array.isArray(row)), + rowCount, + rowOffset: getOptionalNumber(resultValue?.row_offset), + statementId: getOptionalString(statementResponse?.statement_id), + statementState: + statementResponse && isRecord(statementResponse.status) + ? getOptionalString(statementResponse.status.state) + : undefined, + truncated, + statementResponse, + raw: record, + } +} + +export function parseGenerateDownloadFullQueryResultResponse( + value: unknown +): DatabricksGenieGenerateDownloadFullQueryResultResponse { + const record = assertRecord(value, 'Databricks Genie generate download response') + + return { + downloadId: getRequiredString(record.download_id, 'download.download_id'), + downloadIdSignature: getOptionalString(record.download_id_signature), + raw: record, + } +} + +export function parseGetDownloadFullQueryResultResponse( + value: unknown +): DatabricksGenieGetDownloadFullQueryResultResponse { + const record = assertRecord(value, 'Databricks Genie get download response') + + return { + queryResult: parseQueryResult(record), + raw: record, + } +} diff --git a/integrations/ai-sdk-provider/src/genie/shared.ts b/integrations/ai-sdk-provider/src/genie/shared.ts new file mode 100644 index 000000000..a6678796e --- /dev/null +++ b/integrations/ai-sdk-provider/src/genie/shared.ts @@ -0,0 +1,200 @@ +import { combineHeaders, type FetchFunction, withoutTrailingSlash } from '@ai-sdk/provider-utils' + +export type DatabricksGeniePollingSettings = { + timeoutMs?: number + initialPollIntervalMs?: number + maxPollIntervalMs?: number + backoffMultiplier?: number +} + +export interface DatabricksGenieDebugEvent { + body?: unknown + headers?: Record + method: string + metadata?: unknown + phase: 'request' | 'response' + status?: number + statusText?: string + url: string +} + +export type DatabricksGenieDebugLogger = (event: DatabricksGenieDebugEvent) => void + +export type DatabricksGenieDebugSettings = + | boolean + | { + logBodies?: boolean + logger?: DatabricksGenieDebugLogger + } + +export interface DatabricksGenieSettings extends DatabricksGeniePollingSettings { + baseURL: string + debug?: DatabricksGenieDebugSettings + spaceId: string + headers?: Record + fetch?: FetchFunction + formatUrl?: (options: { baseUrl?: string; path: string }) => string +} + +export type DatabricksGenieResolvedSettings = { + baseUrl: string + debug: { + enabled: boolean + logBodies: boolean + logger: DatabricksGenieDebugLogger + } + spaceId: string + headers: () => Record + fetch: FetchFunction + url: (path: string) => string + polling: Required +} + +export const DEFAULT_GENIE_POLLING_SETTINGS: Required = { + timeoutMs: 600_000, + initialPollIntervalMs: 1_000, + maxPollIntervalMs: 60_000, + backoffMultiplier: 2, +} + +export function resolveDatabricksGenieSettings( + settings: DatabricksGenieSettings +): DatabricksGenieResolvedSettings { + const baseUrl: string = withoutTrailingSlash(settings.baseURL) ?? settings.baseURL + const debugSettings = + typeof settings.debug === 'object' && settings.debug !== null ? settings.debug : {} + const debugEnabled = Boolean(settings.debug) + + return { + baseUrl, + debug: { + enabled: debugEnabled, + logBodies: debugSettings.logBodies ?? true, + logger: + debugSettings.logger ?? + ((event) => { + console.debug('[databricks-genie]', event) + }), + }, + spaceId: settings.spaceId, + headers: () => combineHeaders(settings.headers), + fetch: settings.fetch ?? globalThis.fetch.bind(globalThis), + url: (path: string) => settings.formatUrl?.({ baseUrl, path }) ?? `${baseUrl}${path}`, + polling: { + timeoutMs: settings.timeoutMs ?? DEFAULT_GENIE_POLLING_SETTINGS.timeoutMs, + initialPollIntervalMs: + settings.initialPollIntervalMs ?? DEFAULT_GENIE_POLLING_SETTINGS.initialPollIntervalMs, + maxPollIntervalMs: + settings.maxPollIntervalMs ?? DEFAULT_GENIE_POLLING_SETTINGS.maxPollIntervalMs, + backoffMultiplier: + settings.backoffMultiplier ?? DEFAULT_GENIE_POLLING_SETTINGS.backoffMultiplier, + }, + } +} + +export async function ensureOkResponse(response: Response): Promise { + if (!response.ok) { + let body = '' + try { + body = await response.text() + } catch { + // Ignore response body parsing errors and fall back to status text. + } + + throw new Error( + `Databricks Genie request failed with ${response.status} ${response.statusText}${ + body ? `: ${body}` : '' + }` + ) + } +} + +export async function parseJsonResponse(response: Response): Promise { + await ensureOkResponse(response) + + return response.json() +} + +export async function sleep(ms: number, abortSignal?: AbortSignal): Promise { + if (ms <= 0) { + return + } + + await new Promise((resolve, reject) => { + const timer = setTimeout(() => { + abortSignal?.removeEventListener('abort', onAbort) + resolve() + }, ms) + + const onAbort = () => { + clearTimeout(timer) + reject(new Error('Databricks Genie request was aborted')) + } + + if (abortSignal) { + if (abortSignal.aborted) { + onAbort() + return + } + + abortSignal.addEventListener('abort', onAbort, { once: true }) + } + }) +} + +export function getGenieHeaders( + settings: DatabricksGenieResolvedSettings, + headers?: Record +): Record { + const combinedHeaders = combineHeaders( + { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + settings.headers(), + headers + ) + + return Object.fromEntries( + Object.entries(combinedHeaders).filter( + (entry): entry is [string, string] => typeof entry[1] === 'string' + ) + ) +} + +export function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null +} + +export function isStringArray(value: unknown): value is string[] { + return Array.isArray(value) && value.every((item) => typeof item === 'string') +} + +export function sanitizeGenieHeaders( + headers: Record +): Record { + return Object.fromEntries( + Object.entries(headers).map(([key, value]) => { + if ( + key.toLowerCase() === 'authorization' || + key.toLowerCase() === 'cookie' || + key.toLowerCase() === 'set-cookie' + ) { + return [key, '[REDACTED]'] + } + + return [key, value] + }) + ) +} + +export function logGenieDebugEvent( + settings: DatabricksGenieResolvedSettings, + event: DatabricksGenieDebugEvent +): void { + if (!settings.debug.enabled) { + return + } + + settings.debug.logger(event) +} diff --git a/integrations/ai-sdk-provider/src/genie/types.ts b/integrations/ai-sdk-provider/src/genie/types.ts new file mode 100644 index 000000000..0dcff050e --- /dev/null +++ b/integrations/ai-sdk-provider/src/genie/types.ts @@ -0,0 +1,319 @@ +export const DATABRICKS_GENIE_TERMINAL_MESSAGE_STATUSES = [ + 'COMPLETED', + 'FAILED', + 'CANCELLED', + 'QUERY_RESULT_EXPIRED', +] as const + +export const DATABRICKS_GENIE_MESSAGE_STATUSES = [ + 'FETCHING_METADATA', + 'FILTERING_CONTEXT', + 'ASKING_AI', + 'PENDING_WAREHOUSE', + 'EXECUTING_QUERY', + 'FAILED', + 'COMPLETED', + 'SUBMITTED', + 'QUERY_RESULT_EXPIRED', + 'CANCELLED', +] as const + +export const DATABRICKS_GENIE_TEXT_ATTACHMENT_PURPOSES = ['FOLLOW_UP_QUESTION'] as const + +export const DATABRICKS_GENIE_FEEDBACK_RATINGS = ['NEGATIVE', 'NONE', 'POSITIVE'] as const + +export type DatabricksGenieAttachmentType = 'query' | 'text' | 'suggested_questions' + +export type DatabricksGenieMessageStatus = + | (typeof DATABRICKS_GENIE_MESSAGE_STATUSES)[number] + | (string & {}) + +export type DatabricksGenieTextAttachmentPurpose = + | (typeof DATABRICKS_GENIE_TEXT_ATTACHMENT_PURPOSES)[number] + | (string & {}) + +export type DatabricksGenieFeedbackRating = + | (typeof DATABRICKS_GENIE_FEEDBACK_RATINGS)[number] + | (string & {}) + +export interface DatabricksGenieQueryAttachmentParameter { + keyword?: string + sqlType?: string + value?: string + raw: Record +} + +export interface DatabricksGenieQueryAttachmentThought { + content?: string + raw: Record + thoughtType?: string +} + +export interface DatabricksGenieResultMetadata { + isTruncated?: boolean + rowCount?: number + statementId?: string + statementIdSignature?: string + raw: Record +} + +export interface DatabricksGenieQueryAttachment { + attachmentId?: string + description?: string + id?: string + lastUpdatedTimestamp?: number + parameters: DatabricksGenieQueryAttachmentParameter[] + query?: string + queryResultMetadata?: DatabricksGenieResultMetadata + statementId?: string + thoughts: DatabricksGenieQueryAttachmentThought[] + title?: string + raw: Record +} + +export interface DatabricksGenieTextAttachment { + attachmentId?: string + content?: string + id?: string + purpose?: DatabricksGenieTextAttachmentPurpose + raw: Record +} + +export interface DatabricksGenieSuggestedQuestionsAttachment { + attachmentId?: string + questions: string[] + raw: Record +} + +export interface DatabricksGenieAttachment { + attachmentId?: string + query?: DatabricksGenieQueryAttachment + suggestedQuestions?: DatabricksGenieSuggestedQuestionsAttachment + text?: DatabricksGenieTextAttachment + raw: Record +} + +export interface DatabricksGenieNormalizedAttachment { + attachmentId?: string + type: DatabricksGenieAttachmentType + query?: DatabricksGenieQueryAttachment + suggestedQuestions?: DatabricksGenieSuggestedQuestionsAttachment + text?: DatabricksGenieTextAttachment + raw: Record +} + +export interface DatabricksGenieMessageError { + error?: string + type?: string + raw: Record +} + +export interface DatabricksGenieFeedback { + rating?: DatabricksGenieFeedbackRating + raw: Record +} + +export interface DatabricksGenieMessage { + attachments: DatabricksGenieAttachment[] + normalizedAttachments: DatabricksGenieNormalizedAttachment[] + content?: string + conversationId: string + createdTimestamp?: number + error?: DatabricksGenieMessageError + feedback?: DatabricksGenieFeedback + id: string + lastUpdatedTimestamp?: number + legacyId?: string + messageId: string + queryResult?: DatabricksGenieResultMetadata + spaceId?: string + status: DatabricksGenieMessageStatus + userId?: number + raw: Record +} + +export interface DatabricksGenieConversation { + conversationId: string + createdTimestamp?: number + id: string + lastUpdatedTimestamp?: number + legacyId?: string + spaceId?: string + title?: string + userId?: number + raw: Record +} + +export interface DatabricksGenieConversationSummary { + conversationId: string + createdTimestamp?: number + title?: string + raw: Record +} + +export interface DatabricksGenieSampleQuestion { + id?: string + text: string + raw: Record +} + +export interface DatabricksGenieSerializedSpace { + sampleQuestions: DatabricksGenieSampleQuestion[] + raw: Record +} + +export interface DatabricksGenieSpace { + description?: string + id: string + parentPath?: string + serializedSpace?: DatabricksGenieSerializedSpace + serializedSpaceText?: string + spaceId: string + title?: string + warehouseId?: string + raw: Record +} + +export interface DatabricksGenieStartConversationResponse { + conversation: DatabricksGenieConversation + conversationId: string + message: DatabricksGenieMessage + messageId: string + raw: Record +} + +export interface DatabricksGenieListConversationMessagesResponse { + messages: DatabricksGenieMessage[] + nextPageToken?: string + raw: Record +} + +export interface DatabricksGenieListConversationsResponse { + conversations: DatabricksGenieConversationSummary[] + nextPageToken?: string + raw: Record +} + +export interface DatabricksGenieQueryResultColumn { + name: string + typeName?: string +} + +export interface DatabricksGenieQueryResultExternalLink { + byteCount?: number + chunkIndex?: number + expiration?: string + externalLink?: string + httpHeaders?: Record + nextChunkIndex?: number + nextChunkInternalLink?: string + rowCount?: number + rowOffset?: number +} + +export interface DatabricksGenieQueryResult { + columns: DatabricksGenieQueryResultColumn[] + byteCount?: number + chunkIndex?: number + externalLinks: DatabricksGenieQueryResultExternalLink[] + nextChunkIndex?: number + nextChunkInternalLink?: string + rows: unknown[][] + rowCount: number + rowOffset?: number + statementId?: string + statementState?: string + truncated: boolean + statementResponse?: Record + raw: Record +} + +export interface DatabricksGenieGenerateDownloadFullQueryResultResponse { + downloadId: string + downloadIdSignature?: string + raw: Record +} + +export interface DatabricksGenieGetDownloadFullQueryResultResponse { + queryResult: DatabricksGenieQueryResult + raw: Record +} + +export interface DatabricksGenieDownloadQueryResultRequest { + attachmentId: string + conversationId: string + messageId: string +} + +export interface DatabricksGenieDownloadQueryResultResponse { + content: string + contentType: string + fileName: string + queryResult: DatabricksGenieQueryResult +} + +export interface DatabricksGenieStartConversationRequest { + content: string +} + +export interface DatabricksGenieCreateConversationMessageRequest { + content: string + conversationId: string +} + +export interface DatabricksGenieGetConversationMessageRequest { + conversationId: string + messageId: string +} + +export interface DatabricksGenieListConversationMessagesRequest { + conversationId: string + pageSize?: number + pageToken?: string +} + +export interface DatabricksGenieListConversationsRequest { + includeAll?: boolean + pageSize?: number + pageToken?: string +} + +export interface DatabricksGenieDeleteConversationRequest { + conversationId: string +} + +export interface DatabricksGenieGetMessageAttachmentQueryResultRequest { + attachmentId: string + conversationId: string + messageId: string +} + +export interface DatabricksGenieExecuteMessageAttachmentQueryRequest { + attachmentId: string + conversationId: string + messageId: string +} + +export interface DatabricksGenieGenerateDownloadFullQueryResultRequest { + attachmentId: string + conversationId: string + messageId: string +} + +export interface DatabricksGenieGetDownloadFullQueryResultRequest { + attachmentId: string + conversationId: string + downloadId: string + downloadIdSignature?: string + messageId: string +} + +export interface DatabricksGenieGetQueryResultByAttachmentRequest { + attachmentId: string + conversationId: string + messageId: string +} + +export interface DatabricksGenieGetSpaceRequest { + includeSerializedSpace?: boolean +} diff --git a/integrations/ai-sdk-provider/src/index.ts b/integrations/ai-sdk-provider/src/index.ts index ed473545d..60c31a0ea 100644 --- a/integrations/ai-sdk-provider/src/index.ts +++ b/integrations/ai-sdk-provider/src/index.ts @@ -1 +1,2 @@ export * from './databricks-provider' +export * from './genie' diff --git a/integrations/ai-sdk-provider/tests/genie-agent.test.ts b/integrations/ai-sdk-provider/tests/genie-agent.test.ts new file mode 100644 index 000000000..33b541168 --- /dev/null +++ b/integrations/ai-sdk-provider/tests/genie-agent.test.ts @@ -0,0 +1,616 @@ +import { createAgentUIStreamResponse, type UIMessage } from 'ai' +import { describe, expect, it, vi } from 'vitest' +import { createDatabricksGenieAgent } from '../src/genie/agent' + +type MockRoute = { + method: string + path: string + handler: (request: Request, body: unknown) => unknown +} + +function extractMessagePayload(payload: unknown): Record | null { + if (!payload || typeof payload !== 'object') { + return null + } + + const record = payload as Record + + if ( + typeof record.id === 'string' && + typeof record.conversation_id === 'string' && + typeof record.status === 'string' + ) { + return record + } + + const nestedMessage = record.message + if (!nestedMessage || typeof nestedMessage !== 'object') { + return null + } + + const messageRecord = nestedMessage as Record + if ( + typeof messageRecord.id === 'string' && + typeof messageRecord.conversation_id === 'string' && + typeof messageRecord.status === 'string' + ) { + return messageRecord + } + + return null +} + +function createMockFetch(routes: MockRoute[]): typeof globalThis.fetch { + const completedMessages = new Map() + + return vi.fn(async (input: string | URL | Request, init?: RequestInit) => { + const request = input instanceof Request ? input : new Request(input.toString(), init) + const url = new URL(request.url) + let route = routes.find( + (candidate) => candidate.method === request.method && candidate.path === url.pathname + ) + + if (!route && request.method === 'GET') { + const match = url.pathname.match( + /^\/api\/2\.0\/genie\/spaces\/[^/]+\/conversations\/([^/]+)\/messages\/([^/]+)$/ + ) + + if (match) { + const cacheKey = `${match[1]}:${match[2]}` + const cachedPayload = completedMessages.get(cacheKey) + + if (cachedPayload) { + return new Response(JSON.stringify(cachedPayload), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }) + } + } + } + + if (!route) { + return new Response(`Unhandled route: ${request.method} ${url.pathname}`, { status: 404 }) + } + + const bodyText = request.method === 'GET' ? '' : await request.text() + const body = bodyText.length > 0 ? (JSON.parse(bodyText) as unknown) : undefined + const payload = route.handler(request, body) + const messagePayload = extractMessagePayload(payload) + + if ( + messagePayload && + messagePayload.status === 'COMPLETED' && + typeof messagePayload.id === 'string' && + typeof messagePayload.conversation_id === 'string' + ) { + completedMessages.set( + `${messagePayload.conversation_id}:${messagePayload.id}`, + messagePayload + ) + } + + return new Response(JSON.stringify(payload), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }) + }) as unknown as typeof globalThis.fetch +} + +function createAgent(mockFetch: typeof globalThis.fetch) { + return createDatabricksGenieAgent({ + id: 'genie-agent', + baseURL: 'https://example.databricks.com', + spaceId: 'space-123', + headers: { + Authorization: 'Bearer test-token', + }, + fetch: mockFetch, + initialPollIntervalMs: 0, + }) +} + +describe('createDatabricksGenieAgent', () => { + it('uses only the latest user message as the Genie question', async () => { + const agent = createAgent( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: (_request, body) => { + expect(body).toEqual({ content: 'Use this one' }) + + return { + conversation: { id: 'conversation-1' }, + message: { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + text: { content: 'Genie answer' }, + }, + ], + }, + } + }, + }, + ]) + ) + + const result = await agent.generate({ + messages: [ + { role: 'user', content: 'Ignore this older message' }, + { role: 'assistant', content: 'Old response' }, + { role: 'user', content: 'Use this one' }, + ], + options: {}, + }) + + expect(result.text).toBe('Genie answer') + expect(result.genie.conversationId).toBe('conversation-1') + }) + + it('extracts text from multipart user content', async () => { + const agent = createAgent( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: (_request, body) => { + expect(body).toEqual({ content: 'First line\nSecond line' }) + + return { + conversation: { id: 'conversation-1' }, + message: { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + text: { content: 'Multipart answer' }, + }, + ], + }, + } + }, + }, + ]) + ) + + const result = await agent.generate({ + messages: [ + { + role: 'user', + content: [ + { type: 'text', text: 'First line' }, + { type: 'text', text: 'Second line' }, + ], + }, + ], + options: {}, + }) + + expect(result.text).toBe('Multipart answer') + }) + + it('supports generate with structured Genie metadata', async () => { + const agent = createAgent( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { id: 'conversation-1' }, + message: { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-1', + text: { content: 'Sales are up 8%.' }, + }, + { + attachment_id: 'attachment-1', + query: { query: 'SELECT * FROM sales' }, + }, + ], + }, + }), + }, + ]) + ) + + const result = await agent.generate({ + prompt: 'What happened to sales?', + options: {}, + }) + + expect(result.text).toBe('Sales are up 8%.') + expect(result.genie.sql).toBe('SELECT * FROM sales') + expect(result.genie.attachmentId).toBe('attachment-1') + expect(result.genie.attachments).toHaveLength(2) + expect(result.finishReason).toEqual('stop') + expect(result.usage).toMatchObject({ + inputTokens: 0, + outputTokens: 0, + totalTokens: 0, + reasoningTokens: 0, + }) + }) + + it('preserves suggested questions when Genie returns a combined attachment payload', async () => { + const agent = createAgent( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { id: 'conversation-1' }, + message: { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-1', + text: { content: 'Sales are strongest on weekends.' }, + query: { + query: 'SELECT day_of_week, COUNT(*) AS trip_count FROM trips GROUP BY day_of_week', + }, + suggested_questions: { + questions: ['Show the same view by month'], + }, + }, + ], + }, + }), + }, + ]) + ) + + const result = await agent.generate({ + prompt: 'What is the distribution of trips by day of the week?', + options: {}, + }) + + expect(result.text).toBe('Sales are strongest on weekends.') + expect(result.genie.sql).toBe( + 'SELECT day_of_week, COUNT(*) AS trip_count FROM trips GROUP BY day_of_week' + ) + expect(result.genie.suggestedQuestions).toEqual(['Show the same view by month']) + expect(result.genie.attachments.map((attachment) => attachment.type)).toEqual([ + 'text', + 'query', + 'suggested_questions', + ]) + }) + + it('supports stream results for createAgentUIStreamResponse', async () => { + const agent = createAgent( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { id: 'conversation-1' }, + message: { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + text: { content: 'Streaming Genie answer' }, + }, + ], + }, + }), + }, + ]) + ) + + const streamResult = await agent.stream({ + prompt: 'Summarize the dashboard', + options: {}, + }) + + const chunks: string[] = [] + for await (const chunk of streamResult.textStream) { + chunks.push(chunk) + } + + expect(chunks.join('')).toBe('Streaming Genie answer') + await expect(streamResult.genie).resolves.toMatchObject({ + text: 'Streaming Genie answer', + }) + + const response = await createAgentUIStreamResponse({ + agent, + uiMessages: [ + { + id: 'msg-1', + role: 'user', + parts: [{ type: 'text', text: 'Summarize the dashboard' }], + } satisfies UIMessage, + ], + }) + + expect(response).toBeInstanceOf(Response) + }) + + it('emits the expected AI SDK full stream lifecycle and finish metadata', async () => { + const agent = createAgent( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { id: 'conversation-1' }, + message: { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + text: { content: 'Lifecycle answer' }, + }, + ], + }, + }), + }, + ]) + ) + + const streamResult = await agent.stream({ + prompt: 'Show the full stream lifecycle', + options: {}, + }) + + const parts: Array<{ type: string; [key: string]: unknown }> = [] + for await (const part of streamResult.fullStream) { + parts.push(part as { type: string; [key: string]: unknown }) + } + + expect(parts[0]).toMatchObject({ type: 'start' }) + expect(parts[1]).toMatchObject({ type: 'start-step' }) + expect(parts).toContainEqual(expect.objectContaining({ type: 'text-start', id: 'genie-text-0' })) + expect(parts).toContainEqual( + expect.objectContaining({ + type: 'text-delta', + id: 'genie-text-0', + text: 'Lifecycle answer', + }) + ) + expect(parts).toContainEqual(expect.objectContaining({ type: 'text-end', id: 'genie-text-0' })) + + const finishPart = parts.find((part) => part.type === 'finish') + expect(finishPart).toMatchObject({ + type: 'finish', + finishReason: 'stop', + totalUsage: { + inputTokens: 0, + outputTokens: 0, + totalTokens: 0, + }, + }) + }) + + it('emits AI SDK error and error finish metadata when Genie streaming fails', async () => { + const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {}) + const fetch = vi.fn(async () => new Response('boom', { status: 500, statusText: 'Internal Server Error' })) + const agent = createAgent(fetch as unknown as typeof globalThis.fetch) + try { + const streamResult = await agent.stream({ + prompt: 'Trigger a streaming error', + options: {}, + }) + + const parts: Array<{ type: string; [key: string]: unknown }> = [] + for await (const part of streamResult.fullStream) { + parts.push(part as { type: string; [key: string]: unknown }) + } + + expect(parts).toContainEqual(expect.objectContaining({ type: 'error' })) + + const finishPart = parts.find((part) => part.type === 'finish') + expect(finishPart).toMatchObject({ + type: 'finish', + finishReason: 'error', + totalUsage: { + inputTokens: 0, + outputTokens: 0, + totalTokens: 0, + }, + }) + } finally { + consoleError.mockRestore() + } + }) + + it('fetches query results through the agent only when explicitly enabled', async () => { + const fetch = createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { id: 'conversation-1' }, + message: { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-1', + text: { content: 'Query ready' }, + }, + { + attachment_id: 'attachment-1', + query: { query: 'SELECT * FROM dashboard' }, + }, + ], + }, + }), + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-1/messages/message-1/attachments/attachment-1/query-result', + handler: () => ({ + statement_response: { + manifest: { + total_row_count: 2, + truncated: false, + schema: { + columns: [ + { name: 'metric', type_name: 'STRING' }, + { name: 'value', type_name: 'DOUBLE' }, + ], + }, + }, + result: { + data_array: [ + ['revenue', '100'], + ['margin', '20'], + ], + }, + }, + }), + }, + ]) + + const agent = createAgent(fetch) + const result = await agent.generate({ + prompt: 'Fetch the query result too', + options: { + fetchQueryResult: true, + }, + }) + + expect(result.genie.queryResult).toMatchObject({ + rowCount: 2, + columns: [ + { name: 'metric', typeName: 'STRING' }, + { name: 'value', typeName: 'DOUBLE' }, + ], + rows: [ + ['revenue', '100'], + ['margin', '20'], + ], + }) + expect(fetch).toHaveBeenCalledTimes(3) + }) + + it('uses explicit conversation ids for follow-up questions', async () => { + const agent = createAgent( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-9/messages', + handler: (_request, body) => { + expect(body).toEqual({ content: 'Follow up question' }) + + return { + id: 'message-2', + conversation_id: 'conversation-9', + status: 'COMPLETED', + attachments: [ + { + text: { content: 'Follow-up answer' }, + }, + ], + } + }, + }, + ]) + ) + + const result = await agent.generate({ + prompt: 'Follow up question', + options: { + conversationId: 'conversation-9', + }, + }) + + expect(result.genie.conversationId).toBe('conversation-9') + expect(result.text).toBe('Follow-up answer') + }) + + it('does not fetch query results unless explicitly enabled', async () => { + const fetch = createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { id: 'conversation-1' }, + message: { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-1', + text: { content: 'Dashboard updated' }, + }, + { + attachment_id: 'attachment-1', + query: { query: 'SELECT * FROM dashboard' }, + }, + ], + }, + }), + }, + ]) + + const agent = createAgent(fetch) + const result = await agent.generate({ + prompt: 'What changed?', + options: {}, + }) + + expect(result.genie.queryResult).toBeUndefined() + expect(fetch).toHaveBeenCalledTimes(2) + }) + + it('returns fallback text when Genie only provides SQL metadata', async () => { + const agent = createAgent( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { id: 'conversation-1' }, + message: { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-1', + query: { query: 'SELECT * FROM sales' }, + }, + ], + }, + }), + }, + ]) + ) + + const result = await agent.generate({ + prompt: 'Generate SQL', + options: {}, + }) + + expect(result.text).toBe('Genie generated a SQL query for this request.') + expect(result.genie.sql).toBe('SELECT * FROM sales') + }) + + it('throws when no user text is available', async () => { + const agent = createAgent(createMockFetch([])) + + await expect( + agent.generate({ + messages: [{ role: 'assistant', content: 'No user input here' }], + options: {}, + }) + ).rejects.toThrow('requires at least one user message with text content') + }) +}) diff --git a/integrations/ai-sdk-provider/tests/genie-exports.test.ts b/integrations/ai-sdk-provider/tests/genie-exports.test.ts new file mode 100644 index 000000000..c24597dd3 --- /dev/null +++ b/integrations/ai-sdk-provider/tests/genie-exports.test.ts @@ -0,0 +1,20 @@ +import { describe, expect, it } from 'vitest' +import { + createDatabricksGenieAgent, + createDatabricksGenieConversationClient, + createDatabricksProvider, + isLikelyDatabricksGenieFollowUpQuestionAttachment, + isLikelyDatabricksGenieFollowUpQuestionText, + orderDatabricksGenieAttachments, +} from '../src' + +describe('genie package exports', () => { + it('exports the existing Databricks provider alongside Genie entry points', () => { + expect(typeof createDatabricksProvider).toBe('function') + expect(typeof createDatabricksGenieConversationClient).toBe('function') + expect(typeof createDatabricksGenieAgent).toBe('function') + expect(typeof orderDatabricksGenieAttachments).toBe('function') + expect(typeof isLikelyDatabricksGenieFollowUpQuestionAttachment).toBe('function') + expect(typeof isLikelyDatabricksGenieFollowUpQuestionText).toBe('function') + }) +}) diff --git a/integrations/ai-sdk-provider/tests/genie-helper.test.ts b/integrations/ai-sdk-provider/tests/genie-helper.test.ts new file mode 100644 index 000000000..35732d88b --- /dev/null +++ b/integrations/ai-sdk-provider/tests/genie-helper.test.ts @@ -0,0 +1,1548 @@ +import { describe, expect, it, vi } from 'vitest' +import { createDatabricksGenieConversationClient } from '../src/genie/conversation-client' + +type MockRoute = { + method: string + path: string + handler: (request: Request, body: unknown) => unknown +} + +function createMockFetch(routes: MockRoute[]): typeof globalThis.fetch { + return vi.fn(async (input: string | URL | Request, init?: RequestInit) => { + const request = input instanceof Request ? input : new Request(input.toString(), init) + const url = new URL(request.url) + const route = routes.find( + (candidate) => candidate.method === request.method && candidate.path === url.pathname + ) + + if (!route) { + return new Response(`Unhandled route: ${request.method} ${url.pathname}`, { status: 404 }) + } + + const bodyText = request.method === 'GET' ? '' : await request.text() + const body = bodyText.length > 0 ? (JSON.parse(bodyText) as unknown) : undefined + const payload = route.handler(request, body) + + return new Response(JSON.stringify(payload), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }) + }) as unknown as typeof globalThis.fetch +} + +function createHelper(mockFetch: typeof globalThis.fetch) { + return createDatabricksGenieConversationClient({ + baseURL: 'https://example.databricks.com', + spaceId: 'space-123', + headers: { + Authorization: 'Bearer test-token', + }, + fetch: mockFetch, + initialPollIntervalMs: 0, + }) +} + +describe('createDatabricksGenieConversationClient', () => { + it('parses serialized space sample questions', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123', + handler: () => ({ + space_id: 'space-123', + title: 'Taxi analytics', + serialized_space: JSON.stringify({ + version: 2, + config: { + sample_questions: [ + { + id: 'sample-1', + question: ['What is the total number of trips?'], + }, + { + id: 'sample-2', + question: ['Show the top 5 routes by revenue'], + }, + ], + }, + }), + }), + }, + ]) + ) + + const space = await helper.getSpace() + const sampleQuestions = await helper.getSampleQuestions() + + expect(space.id).toBe('space-123') + expect(space.serializedSpace?.sampleQuestions).toEqual([ + { + id: 'sample-1', + text: 'What is the total number of trips?', + raw: { + id: 'sample-1', + question: ['What is the total number of trips?'], + }, + }, + { + id: 'sample-2', + text: 'Show the top 5 routes by revenue', + raw: { + id: 'sample-2', + question: ['Show the top 5 routes by revenue'], + }, + }, + ]) + expect(sampleQuestions.map((question) => question.text)).toEqual([ + 'What is the total number of trips?', + 'Show the top 5 routes by revenue', + ]) + }) + + it('returns no sample questions for integrated Genie spaces that do not expose serialized export', async () => { + const fetch = vi.fn(async () => + new Response( + JSON.stringify({ + error_code: 'BAD_REQUEST', + message: 'Serialized export is not available to integrated Genie spaces.', + }), + { + status: 400, + statusText: 'Bad Request', + headers: { 'Content-Type': 'application/json' }, + } + ) + ) as unknown as typeof globalThis.fetch + + const helper = createHelper(fetch) + + await expect(helper.getSampleQuestions()).resolves.toEqual([]) + }) + + it('parses nested start conversation responses', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { + id: 'conversation-1', + title: 'Initial question', + }, + message: { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'IN_PROGRESS', + attachments: null, + }, + }), + }, + ]) + ) + + const result = await helper.startConversation('How are sales?') + + expect(result.conversation.id).toBe('conversation-1') + expect(result.message.id).toBe('message-1') + expect(result.message.status).toBe('IN_PROGRESS') + }) + + it('parses canonical Java SDK message and conversation fields', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { + conversation_id: 'conversation-10', + id: 'legacy-conversation-10', + created_timestamp: 1710000000000, + last_updated_timestamp: 1710000001000, + space_id: 'space-123', + title: 'Revenue analysis', + user_id: 42, + }, + conversation_id: 'conversation-10', + message: { + message_id: 'message-10', + id: 'legacy-message-10', + conversation_id: 'conversation-10', + created_timestamp: 1710000000001, + last_updated_timestamp: 1710000001001, + space_id: 'space-123', + user_id: 42, + status: 'COMPLETED', + feedback: { + rating: 'POSITIVE', + }, + query_result: { + is_truncated: true, + row_count: 99, + statement_id: 'stmt-legacy', + statement_id_signature: 'sig-legacy', + }, + attachments: [ + { + attachment_id: 'attachment-10', + query: { + id: 'query-10', + description: 'Revenue by route', + last_updated_timestamp: 1710000002000, + parameters: [ + { + keyword: 'limit', + sql_type: 'BIGINT', + value: '5', + }, + ], + query: 'SELECT * FROM revenue LIMIT 5', + query_result_metadata: { + is_truncated: false, + row_count: 5, + }, + statement_id: 'stmt-10', + thoughts: [ + { + thought_type: 'THOUGHT_TYPE_DESCRIPTION', + content: 'Summarize revenue by route.', + }, + ], + title: 'Top routes', + }, + text: { + id: 'text-10', + content: 'Here are the top routes.', + }, + }, + ], + }, + message_id: 'message-10', + }), + }, + ]) + ) + + const result = await helper.startConversation('Show me top routes') + + expect(result.conversation.id).toBe('conversation-10') + expect(result.conversation.legacyId).toBe('legacy-conversation-10') + expect(result.conversation.conversationId).toBe('conversation-10') + expect(result.message.id).toBe('message-10') + expect(result.message.legacyId).toBe('legacy-message-10') + expect(result.message.messageId).toBe('message-10') + expect(result.message.feedback?.rating).toBe('POSITIVE') + expect(result.message.queryResult).toMatchObject({ + isTruncated: true, + rowCount: 99, + statementId: 'stmt-legacy', + }) + expect(result.message.attachments[0]?.query).toMatchObject({ + id: 'query-10', + description: 'Revenue by route', + statementId: 'stmt-10', + title: 'Top routes', + parameters: [{ keyword: 'limit', sqlType: 'BIGINT', value: '5' }], + thoughts: [ + { + thoughtType: 'THOUGHT_TYPE_DESCRIPTION', + content: 'Summarize revenue by route.', + }, + ], + queryResultMetadata: { + isTruncated: false, + rowCount: 5, + }, + }) + expect(result.message.normalizedAttachments.map((attachment) => attachment.type)).toEqual([ + 'query', + 'text', + ]) + }) + + it('supports follow-up conversations and attachment parsing when Genie returns split attachments', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-1/messages', + handler: (_request, body) => { + expect(body).toEqual({ content: 'Show me the same data for this quarter' }) + + return { + id: 'message-2', + conversation_id: 'conversation-1', + status: 'IN_PROGRESS', + attachments: null, + } + }, + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-1/messages/message-2', + handler: () => ({ + id: 'message-2', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-1', + text: { + content: 'Revenue increased 12% quarter over quarter.', + }, + }, + { + attachment_id: 'attachment-1', + query: { + query: 'SELECT * FROM revenue', + description: 'Revenue by quarter', + }, + }, + { + suggested_questions: { + questions: ['Break this down by region'], + }, + }, + ], + }), + }, + ]) + ) + + const result = await helper.ask('Show me the same data for this quarter', { + conversationId: 'conversation-1', + }) + + expect(result.conversationId).toBe('conversation-1') + expect(result.messageId).toBe('message-2') + expect(result.text).toBe('Revenue increased 12% quarter over quarter.') + expect(result.sql).toBe('SELECT * FROM revenue') + expect(result.attachmentId).toBe('attachment-1') + expect(result.suggestedQuestions).toEqual(['Break this down by region']) + expect(result.attachments).toHaveLength(3) + expect(result.attachments[1]).toMatchObject({ + type: 'query', + query: { + description: 'Revenue by quarter', + }, + }) + }) + + it('parses suggested questions when Genie returns query, text, and suggestions in one attachment', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { + id: 'conversation-2', + }, + message: { + id: 'message-3', + conversation_id: 'conversation-2', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-2', + query: { + query: 'SELECT day_of_week, COUNT(*) FROM trips GROUP BY day_of_week', + description: 'Trip counts by day of week', + }, + text: { + content: 'Saturday has the most trips.', + }, + suggested_questions: { + questions: [ + 'Break this down by pickup zip code', + 'Show the same distribution by hour of day', + ], + }, + }, + ], + }, + }), + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-2/messages/message-3', + handler: () => ({ + id: 'message-3', + conversation_id: 'conversation-2', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-2', + query: { + query: 'SELECT day_of_week, COUNT(*) FROM trips GROUP BY day_of_week', + description: 'Trip counts by day of week', + }, + text: { + content: 'Saturday has the most trips.', + }, + suggested_questions: { + questions: [ + 'Break this down by pickup zip code', + 'Show the same distribution by hour of day', + ], + }, + }, + ], + }), + }, + ]) + ) + + const result = await helper.ask('What is the distribution of trips by day of the week?') + + expect(result.text).toBe('Saturday has the most trips.') + expect(result.sql).toBe('SELECT day_of_week, COUNT(*) FROM trips GROUP BY day_of_week') + expect(result.attachmentId).toBe('attachment-2') + expect(result.suggestedQuestions).toEqual([ + 'Break this down by pickup zip code', + 'Show the same distribution by hour of day', + ]) + expect(result.attachments).toHaveLength(3) + expect(result.attachments.map((attachment) => attachment.type)).toEqual([ + 'text', + 'query', + 'suggested_questions', + ]) + }) + + it('aggregates multiple text and suggested-question attachments', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { + id: 'conversation-4', + }, + message: { + id: 'message-5', + conversation_id: 'conversation-4', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-5a', + text: { + content: 'Here are the top 5 routes by revenue.', + }, + }, + ], + }, + }), + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-4/messages/message-5', + handler: () => ({ + id: 'message-5', + conversation_id: 'conversation-4', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-5a', + text: { + content: 'Here are the top 5 routes by revenue.', + }, + }, + { + attachment_id: 'attachment-5b', + text: { + content: 'The highest revenue route is 10023-10023.', + }, + }, + { + attachment_id: 'attachment-5c', + suggested_questions: { + questions: ['Show the top 5 routes by number of trips'], + }, + }, + { + attachment_id: 'attachment-5d', + suggested_questions: { + questions: ['Break this down by pickup zip code'], + }, + }, + ], + }), + }, + ]) + ) + + const result = await helper.ask('What are the top 5 routes by total revenue?') + + expect(result.text).toBe( + 'Here are the top 5 routes by revenue.\n\nThe highest revenue route is 10023-10023.' + ) + expect(result.suggestedQuestions).toEqual([ + 'Show the top 5 routes by number of trips', + 'Break this down by pickup zip code', + ]) + }) + + it('prefers final-summary text attachments over follow-up-question text attachments', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { + id: 'conversation-5', + }, + message: { + id: 'message-6', + conversation_id: 'conversation-5', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-6', + text: { + content: 'Initial placeholder', + }, + }, + ], + }, + }), + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-5/messages/message-6', + handler: () => ({ + id: 'message-6', + conversation_id: 'conversation-5', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-6a', + text: { + id: 'text-summary', + content: 'The top 5 routes by revenue are listed below.', + }, + }, + { + attachment_id: 'attachment-6b', + text: { + id: 'text-follow-up', + content: + 'Would you like to see the top 5 routes strictly by total revenue without including ties?', + purpose: 'FOLLOW_UP_QUESTION', + }, + }, + ], + }), + }, + ]) + ) + + const result = await helper.ask('What are the top 5 routes by total revenue?') + + expect(result.text).toBe('The top 5 routes by revenue are listed below.') + expect( + result.attachments.find( + (attachment) => attachment.type === 'text' && attachment.text?.purpose === 'FOLLOW_UP_QUESTION' + )?.text + ).toMatchObject({ + id: 'text-follow-up', + purpose: 'FOLLOW_UP_QUESTION', + }) + }) + + it('orders attachments using the library display policy and heuristically detects follow-up text', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { + id: 'conversation-6', + }, + message: { + id: 'message-7', + conversation_id: 'conversation-6', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-follow-up', + text: { + content: + 'Would you like to see the total revenue broken down by pickup and dropoff zip codes instead of the combined route identifier?', + }, + }, + { + attachment_id: 'attachment-suggested', + suggested_questions: { + questions: ['Show the top 10 routes by revenue'], + }, + }, + { + attachment_id: 'attachment-answer', + text: { + content: 'The total revenue generated by each route is shown below.', + }, + }, + { + attachment_id: 'attachment-query', + query: { + description: 'Revenue by route', + query: 'SELECT route, total_revenue FROM route_revenue', + }, + }, + ], + }, + }), + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-6/messages/message-7', + handler: () => ({ + id: 'message-7', + conversation_id: 'conversation-6', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-follow-up', + text: { + content: + 'Would you like to see the total revenue broken down by pickup and dropoff zip codes instead of the combined route identifier?', + }, + }, + { + attachment_id: 'attachment-suggested', + suggested_questions: { + questions: ['Show the top 10 routes by revenue'], + }, + }, + { + attachment_id: 'attachment-answer', + text: { + content: 'The total revenue generated by each route is shown below.', + }, + }, + { + attachment_id: 'attachment-query', + query: { + description: 'Revenue by route', + query: 'SELECT route, total_revenue FROM route_revenue', + }, + }, + ], + }), + }, + ]) + ) + + const result = await helper.ask('Show revenue by route') + + expect(result.text).toBe('The total revenue generated by each route is shown below.') + expect(result.attachments.map((attachment) => attachment.type)).toEqual([ + 'text', + 'query', + 'text', + 'suggested_questions', + ]) + expect(result.attachments[0]?.attachmentId).toBe('attachment-answer') + expect(result.attachments[1]?.attachmentId).toBe('attachment-query') + expect(result.attachments[2]?.attachmentId).toBe('attachment-follow-up') + expect(result.attachments[3]?.attachmentId).toBe('attachment-suggested') + }) + + it('re-fetches the completed message to use the finalized attachments', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { + id: 'conversation-3', + }, + message: { + id: 'message-4', + conversation_id: 'conversation-3', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-stale', + text: { + content: 'Interim response', + }, + }, + ], + }, + }), + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-3/messages/message-4', + handler: () => ({ + id: 'message-4', + conversation_id: 'conversation-3', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-final', + text: { + content: 'Final response with complete data', + }, + query: { + query: 'SELECT * FROM trips LIMIT 5', + }, + suggested_questions: { + questions: ['Show the same for revenue'], + }, + }, + ], + }), + }, + ]) + ) + + const result = await helper.ask('Give me a final answer') + + expect(result.text).toBe('Final response with complete data') + expect(result.sql).toBe('SELECT * FROM trips LIMIT 5') + expect(result.suggestedQuestions).toEqual(['Show the same for revenue']) + expect(result.attachmentId).toBe('attachment-final') + }) + + it('retries until a message reaches completion', async () => { + let attempts = 0 + + const helper = createHelper( + createMockFetch([ + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-1/messages/message-1', + handler: () => { + attempts += 1 + + if (attempts === 1) { + return { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'IN_PROGRESS', + attachments: null, + } + } + + return { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [], + } + }, + }, + ]) + ) + + const result = await helper.waitForCompletion('conversation-1', 'message-1') + + expect(result.status).toBe('COMPLETED') + expect(attempts).toBe(2) + }) + + it('raises terminal errors for failed messages', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-1/messages/message-1', + handler: () => ({ + id: 'message-1', + conversation_id: 'conversation-1', + status: 'FAILED', + error: { + error: 'Warehouse unavailable', + type: 'TRANSIENT', + }, + attachments: null, + }), + }, + ]) + ) + + await expect(helper.waitForCompletion('conversation-1', 'message-1')).rejects.toThrow( + 'Warehouse unavailable' + ) + }) + + it('raises terminal errors for cancelled messages', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-1/messages/message-1', + handler: () => ({ + id: 'message-1', + conversation_id: 'conversation-1', + status: 'CANCELLED', + attachments: null, + }), + }, + ]) + ) + + await expect(helper.waitForCompletion('conversation-1', 'message-1')).rejects.toThrow( + 'cancelled' + ) + }) + + it('raises terminal errors for expired query results', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-1/messages/message-1', + handler: () => ({ + id: 'message-1', + conversation_id: 'conversation-1', + status: 'QUERY_RESULT_EXPIRED', + attachments: null, + }), + }, + ]) + ) + + await expect(helper.waitForCompletion('conversation-1', 'message-1')).rejects.toThrow( + 'query result expired' + ) + }) + + it('reports polling progress for intermediate and terminal messages', async () => { + const onProgress = vi.fn() + let attempts = 0 + + const helper = createHelper( + createMockFetch([ + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-1/messages/message-1', + handler: () => { + attempts += 1 + + return attempts === 1 + ? { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'IN_PROGRESS', + attachments: null, + } + : { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [], + } + }, + }, + ]) + ) + + const result = await helper.waitForCompletion('conversation-1', 'message-1', { + onProgress, + }) + + expect(result.status).toBe('COMPLETED') + expect(onProgress).toHaveBeenCalledTimes(2) + expect(onProgress.mock.calls[0]?.[0]).toMatchObject({ status: 'IN_PROGRESS' }) + expect(onProgress.mock.calls[1]?.[0]).toMatchObject({ status: 'COMPLETED' }) + }) + + it('times out if polling never completes', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-1/messages/message-1', + handler: () => ({ + id: 'message-1', + conversation_id: 'conversation-1', + status: 'IN_PROGRESS', + attachments: null, + }), + }, + ]) + ) + + await expect( + helper.waitForCompletion('conversation-1', 'message-1', { + timeoutMs: 1, + }) + ).rejects.toThrow('timed out') + }) + + it('fetches query results only when explicitly enabled', async () => { + const fetch = createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { id: 'conversation-1' }, + message: { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'IN_PROGRESS', + attachments: null, + }, + }), + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-1/messages/message-1', + handler: () => ({ + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-1', + text: { + content: 'Here is the data you requested.', + }, + }, + { + attachment_id: 'attachment-1', + query: { + query: 'SELECT region, revenue FROM quarterly_revenue', + }, + }, + ], + }), + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-1/messages/message-1/attachments/attachment-1/query-result', + handler: () => ({ + statement_response: { + manifest: { + schema: { + columns: [ + { name: 'region', type_name: 'STRING' }, + { name: 'revenue', type_name: 'DOUBLE' }, + ], + }, + }, + result: { + data_array: [ + ['North America', '100'], + ['Europe', '90'], + ], + }, + }, + }), + }, + ]) + + const helper = createHelper(fetch) + const result = await helper.ask('Show quarterly revenue', { + fetchQueryResult: true, + }) + + expect(result.queryResult).toBeDefined() + expect(result.queryResult?.columns).toEqual([ + { name: 'region', typeName: 'STRING' }, + { name: 'revenue', typeName: 'DOUBLE' }, + ]) + expect(result.queryResult?.rows).toEqual([ + ['North America', '100'], + ['Europe', '90'], + ]) + expect(result.attachments).toHaveLength(2) + expect(fetch).toHaveBeenCalledTimes(4) + }) + + it('re-fetches once when the initial message already completed', async () => { + const fetch = createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { id: 'conversation-1' }, + message: { + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + text: { + content: 'Immediate answer', + }, + }, + ], + }, + }), + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-1/messages/message-1', + handler: () => ({ + id: 'message-1', + conversation_id: 'conversation-1', + status: 'COMPLETED', + attachments: [ + { + text: { + content: 'Immediate answer', + }, + }, + ], + }), + }, + ]) + + const helper = createHelper(fetch) + const result = await helper.ask('Answer immediately') + + expect(result.text).toBe('Immediate answer') + expect(fetch).toHaveBeenCalledTimes(2) + }) + + it('lists conversation messages with pagination metadata', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-20/messages', + handler: () => ({ + messages: [ + { + message_id: 'message-20', + conversation_id: 'conversation-20', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-20', + text: { + content: 'Message page content', + }, + }, + ], + }, + ], + next_page_token: 'page-2', + }), + }, + ]) + ) + + const result = await helper.listConversationMessages({ + conversationId: 'conversation-20', + pageSize: 50, + }) + + expect(result.nextPageToken).toBe('page-2') + expect(result.messages[0]?.messageId).toBe('message-20') + expect(result.messages[0]?.normalizedAttachments[0]).toMatchObject({ + type: 'text', + text: { + content: 'Message page content', + }, + }) + }) + + it('supports full query result download helpers', async () => { + const helper = createHelper( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-30/messages/message-30/attachments/attachment-30/downloads', + handler: () => ({ + download_id: 'download-30', + download_id_signature: 'signature-30', + }), + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-30/messages/message-30/attachments/attachment-30/downloads/download-30', + handler: () => ({ + statement_response: { + statement_id: 'statement-30', + status: { + state: 'SUCCEEDED', + }, + manifest: { + total_row_count: 2, + schema: { + columns: [ + { name: 'route', type_name: 'STRING' }, + { name: 'revenue', type_name: 'DOUBLE' }, + ], + }, + }, + result: { + data_array: [ + ['A-B', 12.5], + ['C-D', 10.0], + ], + }, + }, + }), + }, + ]) + ) + + const download = await helper.generateDownloadFullQueryResult({ + attachmentId: 'attachment-30', + conversationId: 'conversation-30', + messageId: 'message-30', + }) + + expect(download).toMatchObject({ + downloadId: 'download-30', + downloadIdSignature: 'signature-30', + }) + + const result = await helper.getDownloadFullQueryResult({ + attachmentId: 'attachment-30', + conversationId: 'conversation-30', + downloadId: download.downloadId, + downloadIdSignature: download.downloadIdSignature, + messageId: 'message-30', + }) + + expect(result.queryResult.columns).toEqual([ + { name: 'route', typeName: 'STRING' }, + { name: 'revenue', typeName: 'DOUBLE' }, + ]) + expect(result.queryResult.statementId).toBe('statement-30') + expect(result.queryResult.statementState).toBe('SUCCEEDED') + expect(result.queryResult.externalLinks).toEqual([]) + expect(result.queryResult.rows).toEqual([ + ['A-B', 12.5], + ['C-D', 10.0], + ]) + expect(result.queryResult.rowCount).toBe(2) + }) + + it('downloads full query results through external links without exposing provider auth headers', async () => { + const fetch = vi.fn(async (input: string | URL | Request, init?: RequestInit) => { + const request = input instanceof Request ? input : new Request(input.toString(), init) + const url = new URL(request.url) + + if ( + request.method === 'POST' && + url.pathname === + '/api/2.0/genie/spaces/space-123/conversations/conversation-31/messages/message-31/attachments/attachment-31/downloads' + ) { + return new Response( + JSON.stringify({ + download_id: 'download-31', + download_id_signature: 'signature-31', + }), + { + status: 200, + headers: { 'Content-Type': 'application/json' }, + } + ) + } + + if ( + request.method === 'GET' && + url.pathname === + '/api/2.0/genie/spaces/space-123/conversations/conversation-31/messages/message-31/attachments/attachment-31/downloads/download-31' + ) { + return new Response( + JSON.stringify({ + statement_response: { + statement_id: 'statement-31', + status: { + state: 'SUCCEEDED', + }, + manifest: { + total_row_count: 2000, + schema: { + columns: [ + { name: 'route', type_name: 'STRING' }, + { name: 'revenue', type_name: 'DOUBLE' }, + ], + }, + }, + result: { + external_links: [ + { + external_link: 'https://downloads.example.com/genie-query.csv', + http_headers: { + 'x-databricks-download-token': 'temporary-secret', + }, + row_count: 2000, + }, + ], + }, + }, + }), + { + status: 200, + headers: { 'Content-Type': 'application/json' }, + } + ) + } + + if ( + request.method === 'GET' && + url.pathname === '/genie-query.csv' + ) { + expect(request.headers.get('authorization')).toBeNull() + expect(request.headers.get('x-databricks-download-token')).toBe('temporary-secret') + + return new Response('route,revenue\nA-B,12.5\n', { + status: 200, + headers: { 'Content-Type': 'text/csv' }, + }) + } + + return new Response(`Unhandled route: ${request.method} ${url.pathname}`, { status: 404 }) + }) as unknown as typeof globalThis.fetch + + const helper = createHelper(fetch) + const result = await helper.downloadQueryResult({ + attachmentId: 'attachment-31', + conversationId: 'conversation-31', + messageId: 'message-31', + }) + + expect(result.content).toBe('route,revenue\nA-B,12.5\n') + expect(result.contentType).toBe('text/csv; charset=utf-8') + expect(result.fileName).toBe('genie-query-result-attachment-31.csv') + expect(result.queryResult.externalLinks).toHaveLength(1) + }) + + it('polls refreshed query results until the rerun succeeds', async () => { + let getQueryResultCount = 0 + + const helper = createHelper( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-32/messages/message-32/attachments/attachment-32/execute-query', + handler: () => ({ + statement_response: { + statement_id: 'statement-32', + status: { + state: 'PENDING', + }, + manifest: { + total_row_count: 2, + schema: { + columns: [ + { name: 'route', type_name: 'STRING' }, + { name: 'revenue', type_name: 'DOUBLE' }, + ], + }, + }, + result: { + row_count: 0, + data_array: [], + }, + }, + }), + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-32/messages/message-32/attachments/attachment-32/query-result', + handler: () => { + getQueryResultCount += 1 + + if (getQueryResultCount === 1) { + return { + statement_response: { + statement_id: 'statement-32', + status: { + state: 'RUNNING', + }, + manifest: { + total_row_count: 2, + schema: { + columns: [ + { name: 'route', type_name: 'STRING' }, + { name: 'revenue', type_name: 'DOUBLE' }, + ], + }, + }, + result: { + row_count: 0, + data_array: [], + }, + }, + } + } + + return { + statement_response: { + statement_id: 'statement-32', + status: { + state: 'SUCCEEDED', + }, + manifest: { + total_row_count: 2, + schema: { + columns: [ + { name: 'route', type_name: 'STRING' }, + { name: 'revenue', type_name: 'DOUBLE' }, + ], + }, + }, + result: { + row_count: 2, + data_array: [ + ['A-B', 12.5], + ['C-D', 10.0], + ], + }, + }, + } + }, + }, + ]) + ) + + const result = await helper.refreshQueryAttachment({ + attachmentId: 'attachment-32', + conversationId: 'conversation-32', + messageId: 'message-32', + }) + + expect(getQueryResultCount).toBe(2) + expect(result.statementState).toBe('SUCCEEDED') + expect(result.rows).toEqual([ + ['A-B', 12.5], + ['C-D', 10.0], + ]) + }) + + it('deletes conversations through the Genie API', async () => { + const fetch = createMockFetch([ + { + method: 'DELETE', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-50', + handler: () => ({}), + }, + ]) + + const helper = createHelper(fetch) + await expect(helper.deleteConversation('conversation-50')).resolves.toBeUndefined() + expect(fetch).toHaveBeenCalledTimes(1) + }) + + it('streams progressive Genie status, attachments, query results, and the final result', async () => { + let messagePollCount = 0 + let queryResultCount = 0 + + const helper = createHelper( + createMockFetch([ + { + method: 'POST', + path: '/api/2.0/genie/spaces/space-123/start-conversation', + handler: () => ({ + conversation: { id: 'conversation-40' }, + message: { + id: 'message-40', + conversation_id: 'conversation-40', + status: 'SUBMITTED', + attachments: [], + }, + }), + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-40/messages/message-40', + handler: () => { + messagePollCount += 1 + + if (messagePollCount === 1) { + return { + id: 'message-40', + conversation_id: 'conversation-40', + status: 'FETCHING_METADATA', + attachments: [], + } + } + + if (messagePollCount === 2) { + return { + id: 'message-40', + conversation_id: 'conversation-40', + status: 'EXECUTING_QUERY', + attachments: [ + { + attachment_id: 'attachment-40', + query: { + description: 'Revenue by route', + query: 'SELECT route, revenue FROM trips ORDER BY revenue DESC LIMIT 5', + }, + }, + ], + } + } + + return { + id: 'message-40', + conversation_id: 'conversation-40', + status: 'COMPLETED', + attachments: [ + { + attachment_id: 'attachment-40', + query: { + description: 'Revenue by route', + query: 'SELECT route, revenue FROM trips ORDER BY revenue DESC LIMIT 5', + thoughts: [ + { + thought_type: 'THOUGHT_TYPE_DESCRIPTION', + content: 'Summarize the highest revenue routes first.', + }, + { + thought_type: 'THOUGHT_TYPE_STEPS', + content: '- Rank routes by revenue\n- Keep the top 5 rows', + }, + ], + }, + }, + { + attachment_id: 'attachment-text-40', + text: { + content: 'The top 5 routes are shown below.', + }, + }, + { + attachment_id: 'attachment-suggested-40', + suggested_questions: { + questions: ['Show the same ranking by month'], + }, + }, + ], + } + }, + }, + { + method: 'GET', + path: '/api/2.0/genie/spaces/space-123/conversations/conversation-40/messages/message-40/attachments/attachment-40/query-result', + handler: () => { + queryResultCount += 1 + + if (queryResultCount === 1) { + return { + statement_response: { + statement_id: 'statement-40', + status: { + state: 'RUNNING', + }, + result: { + row_count: 0, + data_array: [], + }, + }, + } + } + + return { + statement_response: { + statement_id: 'statement-40', + status: { + state: 'SUCCEEDED', + }, + manifest: { + total_row_count: 2, + schema: { + columns: [ + { name: 'route', type_name: 'STRING' }, + { name: 'revenue', type_name: 'DOUBLE' }, + ], + }, + }, + result: { + data_array: [ + ['A-B', 12.5], + ['C-D', 10.0], + ], + }, + }, + } + }, + }, + ]) + ) + + const events = [] + for await (const event of helper.streamConversation('Show the top 5 routes by total revenue', { + fetchQueryResult: true, + })) { + events.push(event) + } + + expect(events.map((event) => event.type)).toEqual([ + 'status', + 'status', + 'status', + 'attachment', + 'status', + 'attachment', + 'attachment', + 'attachment', + 'query-result', + 'complete', + ]) + expect(events.filter((event) => event.type === 'status').map((event) => event.status)).toEqual([ + 'SUBMITTED', + 'FETCHING_METADATA', + 'EXECUTING_QUERY', + 'COMPLETED', + ]) + expect(events.filter((event) => event.type === 'query-result')).toHaveLength(1) + expect(events.find((event) => event.type === 'query-result')).toMatchObject({ + type: 'query-result', + attachmentId: 'attachment-40', + queryResult: { + statementId: 'statement-40', + statementState: 'SUCCEEDED', + columns: [ + { name: 'route', typeName: 'STRING' }, + { name: 'revenue', typeName: 'DOUBLE' }, + ], + rows: [ + ['A-B', 12.5], + ['C-D', 10.0], + ], + }, + }) + expect( + events.find( + (event) => + event.type === 'attachment' && + event.attachment.type === 'query' && + (event.attachment.query?.thoughts.length ?? 0) > 0 + ) + ).toMatchObject({ + type: 'attachment', + attachment: { + type: 'query', + query: { + thoughts: [ + { + thoughtType: 'THOUGHT_TYPE_DESCRIPTION', + content: 'Summarize the highest revenue routes first.', + }, + { + thoughtType: 'THOUGHT_TYPE_STEPS', + content: '- Rank routes by revenue\n- Keep the top 5 rows', + }, + ], + }, + }, + }) + expect(events.at(-1)).toMatchObject({ + type: 'complete', + result: { + text: 'The top 5 routes are shown below.', + suggestedQuestions: ['Show the same ranking by month'], + }, + }) + }) +}) diff --git a/integrations/ai-sdk-provider/tests/genie-live-smoke.test.ts b/integrations/ai-sdk-provider/tests/genie-live-smoke.test.ts new file mode 100644 index 000000000..2693d5859 --- /dev/null +++ b/integrations/ai-sdk-provider/tests/genie-live-smoke.test.ts @@ -0,0 +1,217 @@ +import { beforeAll, describe, expect, it } from 'vitest' +import { createDatabricksGenieAgent, createDatabricksGenieConversationClient } from '../src' + +const RUN_GENIE_LIVE_TEST = process.env.npm_lifecycle_event === 'test:genie:live' + +function getRequiredEnv(name: string): string { + const value = process.env[name]?.trim() + if (!value) { + throw new Error(`Missing required environment variable: ${name}`) + } + + return value +} + +function getLiveSettings() { + return { + baseURL: getRequiredEnv('DATABRICKS_HOST'), + spaceId: getRequiredEnv('DATABRICKS_GENIE_SPACE_ID'), + headers: { + Authorization: `Bearer ${getRequiredEnv('DATABRICKS_TOKEN')}`, + }, + } +} + +function logGenieResult(label: string, result: { + conversationId: string + messageId: string + status: string + text: string + sql?: string + attachmentId?: string + suggestedQuestions?: string[] + queryResult?: { + rowCount: number + columns: Array<{ name: string; typeName?: string }> + rows: unknown[][] + } +}) { + console.log(`\n[${label}]`) + console.log(`conversationId: ${result.conversationId}`) + console.log(`messageId: ${result.messageId}`) + console.log(`status: ${result.status}`) + console.log(`text: ${result.text || ''}`) + + if (result.sql) { + console.log(`sql: ${result.sql}`) + } + + if (result.attachmentId) { + console.log(`attachmentId: ${result.attachmentId}`) + } + + if (result.suggestedQuestions && result.suggestedQuestions.length > 0) { + console.log(`suggestedQuestions: ${result.suggestedQuestions.join(' | ')}`) + } + + if (result.queryResult) { + console.log(`queryResult.rowCount: ${result.queryResult.rowCount}`) + console.log( + `queryResult.columns: ${result.queryResult.columns + .map((column) => `${column.name}${column.typeName ? ` (${column.typeName})` : ''}`) + .join(', ')}` + ) + console.log(`queryResult.previewRows: ${JSON.stringify(result.queryResult.rows.slice(0, 5), null, 2)}`) + } +} + +describe.skipIf(!RUN_GENIE_LIVE_TEST)('Databricks Genie live smoke test', () => { + const question = + process.env.DATABRICKS_GENIE_TEST_QUESTION?.trim() ?? + 'Give me a short summary of the data available in this Genie space.' + + const helper = createDatabricksGenieConversationClient(getLiveSettings()) + const agent = createDatabricksGenieAgent(getLiveSettings()) + + let initialResult: Awaited> + + beforeAll(async () => { + initialResult = await helper.ask(question, { + fetchQueryResult: false, + }) + + if (initialResult.attachmentId && !initialResult.queryResult) { + try { + initialResult = { + ...initialResult, + queryResult: await helper.getQueryResult( + initialResult.conversationId, + initialResult.messageId, + initialResult.attachmentId + ), + } + } catch (error) { + console.log('[helper] query-result fetch was not available:', error instanceof Error ? error.message : error) + } + } + + logGenieResult('helper', initialResult) + console.log( + '[helper.attachments]', + JSON.stringify( + initialResult.message.normalizedAttachments.map((attachment) => ({ + type: attachment.type, + attachmentId: attachment.attachmentId, + rawKeys: Object.keys(attachment.raw), + text: attachment.text?.content, + sql: attachment.query?.query, + suggestedQuestions: attachment.suggestedQuestions?.questions, + })), + null, + 2 + ) + ) + }, 120_000) + + it.sequential( + 'maps raw Genie attachments into normalized helper output', + async () => { + expect(initialResult.conversationId.length).toBeGreaterThan(0) + expect(initialResult.messageId.length).toBeGreaterThan(0) + expect(initialResult.status).toBe('COMPLETED') + expect(initialResult.message.raw).toBeDefined() + expect(initialResult.message.attachments.length).toBeGreaterThan(0) + + const textAttachment = initialResult.message.normalizedAttachments.find( + (attachment) => attachment.type === 'text' + ) + if (textAttachment?.text?.content) { + expect(initialResult.text).toBe(textAttachment.text.content) + } + + const queryAttachment = initialResult.message.normalizedAttachments.find( + (attachment) => attachment.type === 'query' + ) + if (queryAttachment?.query?.query) { + expect(initialResult.sql).toBe(queryAttachment.query.query) + expect(initialResult.attachmentId).toBe(queryAttachment.attachmentId) + } + + const suggestionAttachment = initialResult.message.normalizedAttachments.find( + (attachment) => attachment.type === 'suggested_questions' + ) + if (suggestionAttachment?.suggestedQuestions?.questions) { + expect(initialResult.suggestedQuestions).toEqual(suggestionAttachment.suggestedQuestions.questions) + } + + if (initialResult.queryResult) { + expect(initialResult.queryResult.rowCount).toBeGreaterThanOrEqual(0) + expect(Array.isArray(initialResult.queryResult.columns)).toBe(true) + expect(Array.isArray(initialResult.queryResult.rows)).toBe(true) + } + }, + 120_000 + ) + + it.sequential( + 'uses Genie suggested questions for helper and agent follow-ups', + async () => { + expect(initialResult.suggestedQuestions.length).toBeGreaterThan(0) + + const helperFollowUpQuestion = initialResult.suggestedQuestions[0] + let helperFollowUpResult = await helper.ask(helperFollowUpQuestion, { + conversationId: initialResult.conversationId, + }) + + if (helperFollowUpResult.attachmentId && !helperFollowUpResult.queryResult) { + helperFollowUpResult = { + ...helperFollowUpResult, + queryResult: await helper.getQueryResult( + helperFollowUpResult.conversationId, + helperFollowUpResult.messageId, + helperFollowUpResult.attachmentId + ), + } + } + + logGenieResult('helper-follow-up', helperFollowUpResult) + + expect(helperFollowUpResult.conversationId).toBe(initialResult.conversationId) + expect(helperFollowUpResult.messageId).not.toBe(initialResult.messageId) + expect( + helperFollowUpResult.text.length > 0 || + Boolean(helperFollowUpResult.sql) || + helperFollowUpResult.suggestedQuestions.length > 0 + ).toBe(true) + + const agentFollowUpQuestion = + initialResult.suggestedQuestions[1] ?? + process.env.DATABRICKS_GENIE_TEST_FOLLOW_UP_QUESTION?.trim() ?? + helperFollowUpQuestion + + const agentResult = await agent.generate({ + messages: [ + { role: 'user', content: question }, + { role: 'assistant', content: initialResult.text || 'Genie returned metadata without text.' }, + { role: 'user', content: agentFollowUpQuestion }, + ], + options: { + conversationId: initialResult.conversationId, + fetchQueryResult: true, + }, + }) + + logGenieResult('agent-follow-up', agentResult.genie) + + expect(agentResult.genie.conversationId).toBe(initialResult.conversationId) + expect(agentResult.genie.messageId.length).toBeGreaterThan(0) + expect(agentResult.genie.status).toBe('COMPLETED') + expect( + agentResult.text.length > 0 || + Boolean(agentResult.genie.sql) || + agentResult.genie.suggestedQuestions.length > 0 + ).toBe(true) + }, + 180_000 + ) +}) diff --git a/integrations/ai-sdk-provider/tests/setup.ts b/integrations/ai-sdk-provider/tests/setup.ts index 8e610d735..995ed68b6 100644 --- a/integrations/ai-sdk-provider/tests/setup.ts +++ b/integrations/ai-sdk-provider/tests/setup.ts @@ -1,12 +1,12 @@ -// Test setup file for Vitest -// This file runs before each test file +import fs from 'node:fs' +import path from 'node:path' +import { config as loadEnv } from 'dotenv' -// You can add global test setup here, such as: -// - Mock implementations -// - Global test utilities -// - Environment variable setup - -// Example: Set up test environment variables process.env.NODE_ENV = 'test' -// You can extend expect with custom matchers here if needed +const envLocalPath = path.resolve(process.cwd(), '.env.local') + +// Load local developer secrets for opt-in live tests without affecting CI defaults. +if (fs.existsSync(envLocalPath)) { + loadEnv({ path: envLocalPath, quiet: true }) +}