diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000000..b6d8d73512ff --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +.git +.opencode +.sst +.turbo +.wrangler +node_modules +**/node_modules +**/.output +**/dist +**/.turbo +**/.vite +**/coverage diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7b4f53a98ee0..18e6cf7acb44 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -9,9 +9,15 @@ on: concurrency: ${{ github.workflow }}-${{ github.ref }} +permissions: + contents: read + id-token: write + jobs: deploy: + if: github.repository == 'anomalyco/opencode' && (github.ref_name == 'dev' || github.ref_name == 'production') runs-on: ubuntu-latest + environment: ${{ github.ref_name }} steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 @@ -21,14 +27,11 @@ jobs: with: node-version: "24" - # Workaround for Pulumi version conflict: - # GitHub runners have Pulumi 3.212.0+ pre-installed, which removed the -root flag - # from pulumi-language-nodejs (see https://github.com/pulumi/pulumi/pull/21065). - # SST 3.17.x uses Pulumi SDK 3.210.0 which still passes -root, causing a conflict. - # Removing the system language plugin forces SST to use its bundled compatible version. - # TODO: Remove when sst supports Pulumi >3.210.0 - - name: Fix Pulumi version conflict - run: sudo rm -f /usr/local/bin/pulumi-language-nodejs + - uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 + with: + role-to-assume: ${{ vars.AWS_DEPLOY_ROLE_ARN }} + role-session-name: opencode-${{ github.run_id }} + aws-region: us-east-1 - run: bun sst deploy --stage=${{ github.ref_name }} env: diff --git a/AGENTS.md b/AGENTS.md index 0b1998ec5012..fa39b00a4058 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,8 +1,14 @@ - To regenerate the JavaScript SDK, run `./packages/sdk/js/script/build.ts`. -- ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE. - The default branch in this repo is `dev`. - Local `main` ref may not exist; use `dev` or `origin/dev` for diffs. -- Prefer automation: execute requested actions without confirmation unless blocked by missing info or safety/irreversibility. + +## Commits and PR Titles + +Use conventional commit-style messages and PR titles: `type(scope): summary`. + +Valid types are `feat`, `fix`, `docs`, `chore`, `refactor`, and `test`. Scopes are optional; use the affected package or area when helpful, e.g. `core`, `opencode`, `tui`, `app`, `desktop`, `sdk`, or `plugin`. + +Examples: `fix(tui): simplify thinking toggle styling`, `docs: update contributing guide`, `chore(sdk): regenerate types`. ## Style Guide diff --git a/bun.lock b/bun.lock index 930ee3324363..2b2c1dd915e6 100644 --- a/bun.lock +++ b/bun.lock @@ -23,13 +23,13 @@ "oxlint-tsgolint": "0.21.0", "prettier": "3.6.2", "semver": "^7.6.0", - "sst": "3.18.10", + "sst": "catalog:", "turbo": "2.8.13", }, }, "packages/app": { "name": "@opencode-ai/app", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/core": "workspace:*", @@ -44,6 +44,7 @@ "@solid-primitives/i18n": "2.2.1", "@solid-primitives/media": "2.3.3", "@solid-primitives/resize-observer": "2.1.5", + "@solid-primitives/scheduled": "1.5.3", "@solid-primitives/scroll": "2.1.3", "@solid-primitives/storage": "catalog:", "@solid-primitives/timer": "1.4.4", @@ -84,7 +85,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -101,6 +102,7 @@ "@solidjs/router": "catalog:", "@solidjs/start": "catalog:", "@stripe/stripe-js": "8.6.1", + "@upstash/redis": "1.38.0", "chart.js": "4.5.1", "nitro": "3.0.1-alpha.1", "solid-js": "catalog:", @@ -119,7 +121,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -146,7 +148,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@ai-sdk/anthropic": "3.0.64", "@ai-sdk/openai": "3.0.48", @@ -168,7 +170,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -190,23 +192,43 @@ "cloudflare": "5.2.0", }, }, + "packages/console/support": { + "name": "@opencode-ai/console-support", + "version": "1.15.12", + "dependencies": { + "@cloudflare/vite-plugin": "1.15.2", + "@opencode-ai/console-core": "workspace:*", + "@solidjs/meta": "catalog:", + "@solidjs/router": "catalog:", + "@solidjs/start": "catalog:", + "nitro": "3.0.1-alpha.1", + "solid-js": "catalog:", + "vite": "catalog:", + }, + "devDependencies": { + "@types/bun": "catalog:", + "@typescript/native-preview": "catalog:", + "typescript": "catalog:", + "wrangler": "4.50.0", + }, + }, "packages/core": { "name": "@opencode-ai/core", - "version": "1.15.5", + "version": "1.15.12", "bin": { "opencode": "./bin/opencode", }, "dependencies": { "@ai-sdk/alibaba": "1.0.17", - "@ai-sdk/amazon-bedrock": "4.0.96", + "@ai-sdk/amazon-bedrock": "4.0.107", "@ai-sdk/anthropic": "3.0.71", "@ai-sdk/azure": "3.0.49", "@ai-sdk/cerebras": "2.0.41", "@ai-sdk/cohere": "3.0.27", "@ai-sdk/deepinfra": "2.0.41", "@ai-sdk/gateway": "3.0.104", - "@ai-sdk/google": "3.0.63", - "@ai-sdk/google-vertex": "4.0.112", + "@ai-sdk/google": "3.0.73", + "@ai-sdk/google-vertex": "4.0.128", "@ai-sdk/groq": "3.0.31", "@ai-sdk/mistral": "3.0.27", "@ai-sdk/openai": "3.0.53", @@ -230,7 +252,7 @@ "ai-gateway-provider": "3.1.2", "cross-spawn": "catalog:", "effect": "catalog:", - "gitlab-ai-provider": "6.6.0", + "gitlab-ai-provider": "6.7.0", "glob": "13.0.5", "google-auth-library": "10.5.0", "immer": "11.1.4", @@ -238,7 +260,7 @@ "minimatch": "10.2.5", "npm-package-arg": "13.0.2", "semver": "^7.6.3", - "venice-ai-sdk-provider": "2.0.1", + "venice-ai-sdk-provider": "2.0.2", "xdg-basedir": "5.1.0", "zod": "catalog:", }, @@ -253,8 +275,9 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { + "@zip.js/zip.js": "2.7.62", "drizzle-orm": "catalog:", "effect": "catalog:", "electron-context-menu": "4.1.2", @@ -305,9 +328,23 @@ "@parcel/watcher-win32-x64": "2.5.1", }, }, + "packages/effect-drizzle-sqlite": { + "name": "@opencode-ai/effect-drizzle-sqlite", + "version": "1.15.12", + "dependencies": { + "drizzle-orm": "catalog:", + "effect": "catalog:", + }, + "devDependencies": { + "@effect/sql-sqlite-bun": "catalog:", + "@tsconfig/bun": "catalog:", + "@types/bun": "catalog:", + "@typescript/native-preview": "catalog:", + }, + }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@opencode-ai/core": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -337,7 +374,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -353,7 +390,7 @@ }, "packages/http-recorder": { "name": "@opencode-ai/http-recorder", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@effect/platform-node": "catalog:", "effect": "catalog:", @@ -366,7 +403,7 @@ }, "packages/llm": { "name": "@opencode-ai/llm", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@smithy/eventstream-codec": "4.2.14", "@smithy/util-utf8": "4.2.2", @@ -384,7 +421,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.15.5", + "version": "1.15.12", "bin": { "opencode": "./bin/opencode", }, @@ -393,15 +430,15 @@ "@actions/github": "6.0.1", "@agentclientprotocol/sdk": "0.21.0", "@ai-sdk/alibaba": "1.0.17", - "@ai-sdk/amazon-bedrock": "4.0.96", + "@ai-sdk/amazon-bedrock": "4.0.107", "@ai-sdk/anthropic": "3.0.71", "@ai-sdk/azure": "3.0.49", "@ai-sdk/cerebras": "2.0.41", "@ai-sdk/cohere": "3.0.27", "@ai-sdk/deepinfra": "2.0.41", "@ai-sdk/gateway": "3.0.104", - "@ai-sdk/google": "3.0.63", - "@ai-sdk/google-vertex": "4.0.112", + "@ai-sdk/google": "3.0.73", + "@ai-sdk/google-vertex": "4.0.128", "@ai-sdk/groq": "3.0.31", "@ai-sdk/mistral": "3.0.27", "@ai-sdk/openai": "3.0.53", @@ -441,6 +478,7 @@ "@solid-primitives/event-bus": "1.1.2", "@solid-primitives/scheduled": "1.5.2", "@standard-schema/spec": "1.0.0", + "@types/ws": "8.18.1", "@zip.js/zip.js": "2.7.62", "ai": "catalog:", "ai-gateway-provider": "3.1.2", @@ -454,7 +492,7 @@ "drizzle-orm": "catalog:", "effect": "catalog:", "fuzzysort": "3.1.0", - "gitlab-ai-provider": "6.6.0", + "gitlab-ai-provider": "6.7.0", "glob": "13.0.5", "google-auth-library": "10.5.0", "gray-matter": "4.0.3", @@ -478,10 +516,11 @@ "tree-sitter-powershell": "0.25.10", "turndown": "7.2.0", "ulid": "catalog:", - "venice-ai-sdk-provider": "2.0.1", + "venice-ai-sdk-provider": "2.0.2", "vscode-jsonrpc": "8.2.1", "web-tree-sitter": "0.25.10", "which": "6.0.1", + "ws": "8.21.0", "xdg-basedir": "5.1.0", "yargs": "18.0.0", "zod": "catalog:", @@ -522,7 +561,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@opencode-ai/sdk": "workspace:*", "effect": "catalog:", @@ -538,9 +577,9 @@ "typescript": "catalog:", }, "peerDependencies": { - "@opentui/core": ">=0.2.14", - "@opentui/keymap": ">=0.2.14", - "@opentui/solid": ">=0.2.14", + "@opentui/core": ">=0.2.16", + "@opentui/keymap": ">=0.2.16", + "@opentui/solid": ">=0.2.16", }, "optionalPeers": [ "@opentui/core", @@ -560,7 +599,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "cross-spawn": "catalog:", }, @@ -575,7 +614,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -586,6 +625,67 @@ "typescript": "catalog:", }, }, + "packages/stats/app": { + "name": "@opencode-ai/stats-app", + "version": "1.15.12", + "dependencies": { + "@ibm/plex": "6.4.1", + "@opencode-ai/stats-core": "workspace:*", + "@opencode-ai/ui": "workspace:*", + "@solidjs/meta": "catalog:", + "@solidjs/router": "catalog:", + "@solidjs/start": "catalog:", + "d3-scale": "4.0.2", + "effect": "catalog:", + "nitro": "3.0.1-alpha.1", + "solid-js": "catalog:", + "vite": "catalog:", + }, + "devDependencies": { + "@cloudflare/workers-types": "catalog:", + "@types/bun": "catalog:", + "@types/d3-scale": "4.0.9", + "@typescript/native-preview": "catalog:", + "typescript": "catalog:", + }, + }, + "packages/stats/core": { + "name": "@opencode-ai/stats-core", + "version": "1.15.12", + "dependencies": { + "@aws-sdk/client-athena": "3.933.0", + "@planetscale/database": "1.19.0", + "drizzle-orm": "catalog:", + "effect": "catalog:", + "sst": "catalog:", + }, + "devDependencies": { + "@tsconfig/node22": "catalog:", + "@types/bun": "catalog:", + "@types/node": "catalog:", + "@typescript/native-preview": "catalog:", + "drizzle-kit": "catalog:", + "typescript": "catalog:", + }, + }, + "packages/stats/server": { + "name": "@opencode-ai/stats-server", + "version": "1.15.12", + "dependencies": { + "@aws-sdk/client-firehose": "3.933.0", + "@effect/platform-node": "catalog:", + "@opencode-ai/stats-core": "workspace:*", + "effect": "catalog:", + "sst": "catalog:", + }, + "devDependencies": { + "@tsconfig/node22": "catalog:", + "@types/bun": "catalog:", + "@types/node": "catalog:", + "@typescript/native-preview": "catalog:", + "typescript": "catalog:", + }, + }, "packages/storybook": { "name": "@opencode-ai/storybook", "devDependencies": { @@ -610,7 +710,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/core": "workspace:*", @@ -659,7 +759,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.15.5", + "version": "1.15.12", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", @@ -702,6 +802,9 @@ ], "patchedDependencies": { "solid-js@1.9.10": "patches/solid-js@1.9.10.patch", + "virtua@0.49.1": "patches/virtua@0.49.1.patch", + "gcp-metadata@8.1.2": "patches/gcp-metadata@8.1.2.patch", + "@ai-sdk/xai@3.0.82": "patches/@ai-sdk%2Fxai@3.0.82.patch", "@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch", "@npmcli/agent@4.0.0": "patches/@npmcli%2Fagent@4.0.0.patch", "@silvia-odwyer/photon-node@0.3.4": "patches/@silvia-odwyer%2Fphoton-node@0.3.4.patch", @@ -715,17 +818,18 @@ }, "catalog": { "@cloudflare/workers-types": "4.20251008.0", - "@effect/opentelemetry": "4.0.0-beta.65", - "@effect/platform-node": "4.0.0-beta.65", + "@effect/opentelemetry": "4.0.0-beta.66", + "@effect/platform-node": "4.0.0-beta.66", + "@effect/sql-sqlite-bun": "4.0.0-beta.66", "@hono/zod-validator": "0.4.2", "@kobalte/core": "0.13.11", "@lydell/node-pty": "1.2.0-beta.10", "@npmcli/arborist": "9.4.0", "@octokit/rest": "22.0.0", "@openauthjs/openauth": "0.0.0-20250322224806", - "@opentui/core": "0.2.14", - "@opentui/keymap": "0.2.14", - "@opentui/solid": "0.2.14", + "@opentui/core": "0.2.16", + "@opentui/keymap": "0.2.16", + "@opentui/solid": "0.2.16", "@pierre/diffs": "1.1.0-beta.18", "@playwright/test": "1.59.1", "@sentry/solid": "10.36.0", @@ -747,9 +851,9 @@ "cross-spawn": "7.0.6", "diff": "8.0.2", "dompurify": "3.3.1", - "drizzle-kit": "1.0.0-beta.19-d95b7a4", - "drizzle-orm": "1.0.0-beta.19-d95b7a4", - "effect": "4.0.0-beta.65", + "drizzle-kit": "1.0.0-rc.2", + "drizzle-orm": "1.0.0-rc.2", + "effect": "4.0.0-beta.66", "fuzzysort": "3.1.0", "hono": "4.10.7", "hono-openapi": "1.1.2", @@ -763,6 +867,7 @@ "shiki": "3.20.0", "solid-js": "1.9.10", "solid-list": "0.3.0", + "sst": "4.13.1", "tailwindcss": "4.1.11", "typescript": "5.8.2", "ulid": "3.0.1", @@ -792,7 +897,7 @@ "@ai-sdk/alibaba": ["@ai-sdk/alibaba@1.0.17", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.41", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZbE+U5bWz2JBc5DERLowx5+TKbjGBE93LqKZAWvuEn7HOSQMraxFMZuc0ST335QZJAyfBOzh7m1mPQ+y7EaaoA=="], - "@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@4.0.96", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.71", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Mc4Ias2jRMD1jOB6xWtKNPdhECeuCZyIlbr9EAGfBnyBt++sS13ziZh9qv9TdyMCAZJ7xoQcpbchoRJcKwPdpA=="], + "@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@4.0.107", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.78", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8nT08pGPy25rleJNk56ep00UHK6kCtCmu+ZNqVVSSPDieADlIZqcaN1iRXAFBoCH0Fb9F6C2EjFDaySdsargfQ=="], "@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.64", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-rwLi/Rsuj2pYniQXIrvClHvXDzgM4UQHHnvHTWEF14efnlKclG/1ghpNC+adsRujAbCTr6gRsSbDE2vEqriV7g=="], @@ -814,9 +919,9 @@ "@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.104", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZKX5n74io8VIRlhIMSLWVlvT3sXC8Z7cZ9GHuWBWZDVi96+62AIsWuLGvMfcBA1STYuSoDrp6rIziZmvrTq0TA=="], - "@ai-sdk/google": ["@ai-sdk/google@3.0.63", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-RfOZWVMYSPu2sPRfGajrauWAZ9BSaRopSn+AszkKWQ1MFj8nhaXvCqRHB5pBQUaHTfZKagvOmMpNfa/s3gPLgQ=="], + "@ai-sdk/google": ["@ai-sdk/google@3.0.73", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-o2MuIeyvZrFIeIbnbA8Thrr63irdyUBh0uWBZ2lY6yFeXuE/tcwyXF74bDKS4KvTu84uFpQfpbS/LXHGKKXz+g=="], - "@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@4.0.112", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.71", "@ai-sdk/google": "3.0.64", "@ai-sdk/openai-compatible": "2.0.41", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-cSfHCkM+9ZrFtQWIN1WlV93JPD+isGSdFxKj7u1L9m2aLVZajlXdcE41GL9hMt7ld7bZYE4NnZ+4VLxBAHE+Eg=="], + "@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@4.0.128", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.77", "@ai-sdk/google": "3.0.73", "@ai-sdk/openai-compatible": "2.0.47", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "google-auth-library": "^10.5.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-jK8fixb4km2yfgvb9DUFQRpV/jiDB0v9gyxHoHfPydaQvz+CpAz8DTt1quyaM+Wg9G2R8Zo68CYmHbIkUqW2AA=="], "@ai-sdk/groq": ["@ai-sdk/groq@3.0.31", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-XbbugpnFmXGu2TlXiq8KUJskP6/VVbuFcnFIGDzDIB/Chg6XHsNnqrTF80Zxkh0Pd3+NvbM+2Uqrtsndk6bDAg=="], @@ -888,8 +993,14 @@ "@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="], + "@aws-sdk/client-athena": ["@aws-sdk/client-athena@3.933.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.932.0", "@aws-sdk/credential-provider-node": "3.933.0", "@aws-sdk/middleware-host-header": "3.930.0", "@aws-sdk/middleware-logger": "3.930.0", "@aws-sdk/middleware-recursion-detection": "3.933.0", "@aws-sdk/middleware-user-agent": "3.932.0", "@aws-sdk/region-config-resolver": "3.930.0", "@aws-sdk/types": "3.930.0", "@aws-sdk/util-endpoints": "3.930.0", "@aws-sdk/util-user-agent-browser": "3.930.0", "@aws-sdk/util-user-agent-node": "3.932.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.2", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.9", "@smithy/middleware-retry": "^4.4.9", "@smithy/middleware-serde": "^4.2.5", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.8", "@smithy/util-defaults-mode-node": "^4.2.11", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-9eMUCu1Ay3C9ojo+dJcynSdpbxuwDVtZUt/Xhce+c2+mgDsmvRzjww+wfLpZwRNWxBWmeauQQAZk52tCwQgXsQ=="], + "@aws-sdk/client-cognito-identity": ["@aws-sdk/client-cognito-identity@3.993.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.11", "@aws-sdk/credential-provider-node": "^3.972.10", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", "@aws-sdk/middleware-user-agent": "^3.972.11", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.993.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", "@aws-sdk/util-user-agent-node": "^3.972.9", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.23.2", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.16", "@smithy/middleware-retry": "^4.4.33", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.10", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.5", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.32", "@smithy/util-defaults-mode-node": "^4.2.35", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-7Ne3Yk/bgQPVebAkv7W+RfhiwTRSbfER9BtbhOa2w/+dIr902LrJf6vrZlxiqaJbGj2ALx8M+ZK1YIHVxSwu9A=="], + "@aws-sdk/client-firehose": ["@aws-sdk/client-firehose@3.933.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.932.0", "@aws-sdk/credential-provider-node": "3.933.0", "@aws-sdk/middleware-host-header": "3.930.0", "@aws-sdk/middleware-logger": "3.930.0", "@aws-sdk/middleware-recursion-detection": "3.933.0", "@aws-sdk/middleware-user-agent": "3.932.0", "@aws-sdk/region-config-resolver": "3.930.0", "@aws-sdk/types": "3.930.0", "@aws-sdk/util-endpoints": "3.930.0", "@aws-sdk/util-user-agent-browser": "3.930.0", "@aws-sdk/util-user-agent-node": "3.932.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.2", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.9", "@smithy/middleware-retry": "^4.4.9", "@smithy/middleware-serde": "^4.2.5", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.8", "@smithy/util-defaults-mode-node": "^4.2.11", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-tDrtgczN2lQsflLDPYu/wdOoyCZLVYtgzmWnYzSEOBWd/cp2AbuQ7D+FemSwUTzyoMTuhhIevyEJKzqsF+QYxA=="], + + "@aws-sdk/client-lambda": ["@aws-sdk/client-lambda@3.1048.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.11", "@aws-sdk/credential-provider-node": "^3.972.42", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/fetch-http-handler": "^5.4.2", "@smithy/node-http-handler": "^4.7.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-ryEYNVdilyWkKsOs/7Xy/l7+qjtSz4sll8NpcWD6AtONxjG/5OMaAhxxDkQb4iBoNMKnISxsARzQAp/Wa8pXIg=="], + "@aws-sdk/client-s3": ["@aws-sdk/client-s3@3.933.0", "", { "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.932.0", "@aws-sdk/credential-provider-node": "3.933.0", "@aws-sdk/middleware-bucket-endpoint": "3.930.0", "@aws-sdk/middleware-expect-continue": "3.930.0", "@aws-sdk/middleware-flexible-checksums": "3.932.0", "@aws-sdk/middleware-host-header": "3.930.0", "@aws-sdk/middleware-location-constraint": "3.930.0", "@aws-sdk/middleware-logger": "3.930.0", "@aws-sdk/middleware-recursion-detection": "3.933.0", "@aws-sdk/middleware-sdk-s3": "3.932.0", "@aws-sdk/middleware-ssec": "3.930.0", "@aws-sdk/middleware-user-agent": "3.932.0", "@aws-sdk/region-config-resolver": "3.930.0", "@aws-sdk/signature-v4-multi-region": "3.932.0", "@aws-sdk/types": "3.930.0", "@aws-sdk/util-endpoints": "3.930.0", "@aws-sdk/util-user-agent-browser": "3.930.0", "@aws-sdk/util-user-agent-node": "3.932.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.2", "@smithy/eventstream-serde-browser": "^4.2.5", "@smithy/eventstream-serde-config-resolver": "^4.3.5", "@smithy/eventstream-serde-node": "^4.2.5", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-blob-browser": "^4.2.6", "@smithy/hash-node": "^4.2.5", "@smithy/hash-stream-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/md5-js": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.9", "@smithy/middleware-retry": "^4.4.9", "@smithy/middleware-serde": "^4.2.5", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.8", "@smithy/util-defaults-mode-node": "^4.2.11", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-stream": "^4.5.6", "@smithy/util-utf8": "^4.2.0", "@smithy/util-waiter": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-KxwZvdxdCeWK6o8mpnb+kk7Kgb8V+8AjTwSXUWH1UAD85B0tjdo1cSfE5zoR5fWGol4Ml5RLez12a6LPhsoTqA=="], "@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.933.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.932.0", "@aws-sdk/middleware-host-header": "3.930.0", "@aws-sdk/middleware-logger": "3.930.0", "@aws-sdk/middleware-recursion-detection": "3.933.0", "@aws-sdk/middleware-user-agent": "3.932.0", "@aws-sdk/region-config-resolver": "3.930.0", "@aws-sdk/types": "3.930.0", "@aws-sdk/util-endpoints": "3.930.0", "@aws-sdk/util-user-agent-browser": "3.930.0", "@aws-sdk/util-user-agent-node": "3.932.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.2", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.9", "@smithy/middleware-retry": "^4.4.9", "@smithy/middleware-serde": "^4.2.5", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.8", "@smithy/util-defaults-mode-node": "^4.2.11", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-zwGLSiK48z3PzKpQiDMKP85+fpIrPMF1qQOQW9OW7BGj5AuBZIisT2O4VzIgYJeh+t47MLU7VgBQL7muc+MJDg=="], @@ -960,6 +1071,8 @@ "@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.930.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" } }, "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA=="], + "@aws/durable-execution-sdk-js": ["@aws/durable-execution-sdk-js@1.0.2", "", { "dependencies": { "@aws-sdk/client-lambda": "^3.943.0" } }, "sha512-KIYBVqV9gArkWdPEDYOjJqLlO+NecmCXOXadNBlOspJTmqztwuiyb6aZc468bYWSGuL4Me/gyTIK97ubkwFNCw=="], + "@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.4", "", {}, "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ=="], "@azure-rest/core-client": ["@azure-rest/core-client@2.6.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-rest-pipeline": "^1.22.0", "@azure/core-tracing": "^1.3.0", "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-iuFKDm8XPzNxPfRjhyU5/xKZmcRDzSuEghXDHHk4MjBV/wFL34GmYVBZnn9wmuoLBeS1qAw9ceMdaeJBPcB1QQ=="], @@ -1108,11 +1221,13 @@ "@drizzle-team/brocli": ["@drizzle-team/brocli@0.11.0", "", {}, "sha512-hD3pekGiPg0WPCCGAZmusBBJsDqGUR66Y452YgQsZOnkdQ7ViEPKuyP4huUGEZQefp8g34RRodXYmJ2TbCH+tg=="], - "@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-beta.65", "", { "peerDependencies": { "@opentelemetry/api": "^1.9", "@opentelemetry/api-logs": ">=0.203.0 <0.300.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": "^2.0.0", "@opentelemetry/sdk-trace-base": "^2.0.0", "@opentelemetry/sdk-trace-node": "^2.0.0", "@opentelemetry/sdk-trace-web": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.33.0", "effect": "^4.0.0-beta.65" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/api-logs", "@opentelemetry/resources", "@opentelemetry/sdk-logs", "@opentelemetry/sdk-metrics", "@opentelemetry/sdk-trace-base", "@opentelemetry/sdk-trace-node", "@opentelemetry/sdk-trace-web"] }, "sha512-0CD2fSsXrDM7FP2WFkbGJO1DwMqWR3UKHh6oBDXPHAPA+RsJSKoh3pLQsbQfldLuKnhOy87Bv0v9r9IdrIHCQw=="], + "@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-beta.66", "", { "peerDependencies": { "@opentelemetry/api": "^1.9", "@opentelemetry/api-logs": ">=0.203.0 <0.300.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": "^2.0.0", "@opentelemetry/sdk-trace-base": "^2.0.0", "@opentelemetry/sdk-trace-node": "^2.0.0", "@opentelemetry/sdk-trace-web": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.33.0", "effect": "^4.0.0-beta.66" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/api-logs", "@opentelemetry/resources", "@opentelemetry/sdk-logs", "@opentelemetry/sdk-metrics", "@opentelemetry/sdk-trace-base", "@opentelemetry/sdk-trace-node", "@opentelemetry/sdk-trace-web"] }, "sha512-LU3ejAzJS+4P+Qtfn9ULnsGcIPmx1tUUB2ZswFRL+EolD8US7zMljHTwGuQRUBJOjDwt7wFCMN5AR512vdY8FQ=="], + + "@effect/platform-node": ["@effect/platform-node@4.0.0-beta.66", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.66", "mime": "^4.1.0", "undici": "^8.0.2" }, "peerDependencies": { "effect": "^4.0.0-beta.66", "ioredis": "^5.7.0" } }, "sha512-s/0RgaQFuszzdorRnX1PwEQNnSOi+JgMJo3zEe9O2NR3sosMhTr0Uk+1AF6bUOI9uJ2CPT3KpTIIU7q5/TpOkg=="], - "@effect/platform-node": ["@effect/platform-node@4.0.0-beta.65", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.65", "mime": "^4.1.0", "undici": "^8.0.2" }, "peerDependencies": { "effect": "^4.0.0-beta.65", "ioredis": "^5.7.0" } }, "sha512-QQy3KRcMwP0TngQdfQGl2u1zp03B7k7DuF5SNS8aZhD0dDBpKZpCwFad1ODY5qdY3ycPgMwBwKRRK7y/aw0C9w=="], + "@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-beta.66", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.20.0" }, "peerDependencies": { "effect": "^4.0.0-beta.66" } }, "sha512-+ymrhBnESv/hmn5SKTe2//IY9Ox/hGPeoogEWhW47ZGyhFI5eMYFxdEUBa+3IAV05rrBzrxON9lynu68n0DM7w=="], - "@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-beta.65", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.20.0" }, "peerDependencies": { "effect": "^4.0.0-beta.65" } }, "sha512-3rY8F3WLEax6Hj08GI/OvDIH+KqjfxH7RM2bAMfgR75NgRmwDtny1P49PtPkoRjH5dcdtThThtsvE4X9OTZkpQ=="], + "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-beta.66", "", { "peerDependencies": { "effect": "^4.0.0-beta.66" } }, "sha512-UYsrAb/5T0ZRypeN9Kmv3/ZInibGCjM6dtoiAWtfG+xKyuq8N05wmuVCXB0+XgVmUBxDWjw/S1fu4ivS0vZVuw=="], "@electron/asar": ["@electron/asar@3.4.1", "", { "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", "minimatch": "^3.0.4" }, "bin": { "asar": "bin/asar.js" } }, "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA=="], @@ -1444,6 +1559,8 @@ "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.3", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ=="], + "@nodable/entities": ["@nodable/entities@2.1.0", "", {}, "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA=="], + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], @@ -1538,10 +1655,14 @@ "@opencode-ai/console-resource": ["@opencode-ai/console-resource@workspace:packages/console/resource"], + "@opencode-ai/console-support": ["@opencode-ai/console-support@workspace:packages/console/support"], + "@opencode-ai/core": ["@opencode-ai/core@workspace:packages/core"], "@opencode-ai/desktop": ["@opencode-ai/desktop@workspace:packages/desktop"], + "@opencode-ai/effect-drizzle-sqlite": ["@opencode-ai/effect-drizzle-sqlite@workspace:packages/effect-drizzle-sqlite"], + "@opencode-ai/enterprise": ["@opencode-ai/enterprise@workspace:packages/enterprise"], "@opencode-ai/function": ["@opencode-ai/function@workspace:packages/function"], @@ -1558,6 +1679,12 @@ "@opencode-ai/slack": ["@opencode-ai/slack@workspace:packages/slack"], + "@opencode-ai/stats-app": ["@opencode-ai/stats-app@workspace:packages/stats/app"], + + "@opencode-ai/stats-core": ["@opencode-ai/stats-core@workspace:packages/stats/core"], + + "@opencode-ai/stats-server": ["@opencode-ai/stats-server@workspace:packages/stats/server"], + "@opencode-ai/storybook": ["@opencode-ai/storybook@workspace:packages/storybook"], "@opencode-ai/ui": ["@opencode-ai/ui@workspace:packages/ui"], @@ -1592,23 +1719,23 @@ "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.40.0", "", {}, "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw=="], - "@opentui/core": ["@opentui/core@0.2.14", "", { "dependencies": { "bun-ffi-structs": "0.2.2", "diff": "9.0.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@opentui/core-darwin-arm64": "0.2.14", "@opentui/core-darwin-x64": "0.2.14", "@opentui/core-linux-arm64": "0.2.14", "@opentui/core-linux-x64": "0.2.14", "@opentui/core-win32-arm64": "0.2.14", "@opentui/core-win32-x64": "0.2.14" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-17YCr3BqM9mhi/DdNVM+omgmrKQNIl0G5RzoaTFOHe4+OAhG+W3iooYi+WdsekJWSUOEwZqDRz0QBTZhOtgZsQ=="], + "@opentui/core": ["@opentui/core@0.2.16", "", { "dependencies": { "bun-ffi-structs": "0.2.2", "diff": "9.0.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@opentui/core-darwin-arm64": "0.2.16", "@opentui/core-darwin-x64": "0.2.16", "@opentui/core-linux-arm64": "0.2.16", "@opentui/core-linux-x64": "0.2.16", "@opentui/core-win32-arm64": "0.2.16", "@opentui/core-win32-x64": "0.2.16" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-4vWN15Zc3nsXJlOiHhhpqkBXD+wrNFKxCPtiTiillZYDRre+XsZogVTOOGUDwaBIC23OSxq7imezLmmtShVBEA=="], - "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.2.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-iS4NZQkOKX2EP5rsNjDcU7inDLcKhPaSBn8ENjDXKx2smOh7p/rgM2qlEaiLI3njtL784QoF+nxTzSXbEI6+Jw=="], + "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.2.16", "", { "os": "darwin", "cpu": "arm64" }, "sha512-aFb2Yp+oqDu3h6VCWi7xpQ9yjpKSQcROzGGfHgqC6Nd3U+uiLfPJBkmiI87iK0opCggCFj5TkKI004050DmGjg=="], - "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.2.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-ft4ZwYHCV0VtRMwQtHH5mAgwqRLHEXP26DWcwtCZWDEHDvghClBR0cj9UZLH5JAKn/j7ds5hZDCCZz+nUiEHYA=="], + "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.2.16", "", { "os": "darwin", "cpu": "x64" }, "sha512-KimiHE0j7EsTB5P8doW0lr1eH5iZKLPKWQO+tmy1VcdYr/TzqhdHSvGuJXrZvfTFi9/rV57Eq0d7964Ri9O0vQ=="], - "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.2.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-t/EKD4+rlzWuwYAa6NzGCmiBOHvF+hzjNwExj+dnSqX5wK7TU+VHl+N2iYUl4VhhJK94kPP6BnrF5GcHnZGFLg=="], + "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.2.16", "", { "os": "linux", "cpu": "arm64" }, "sha512-4fCwRCfTtUgS/5QcSEkSuBjgQymSOUWXgrXG2ycrf3Swi0QhKDA/pVjwLrUJ6eF+/8mQyQSEV72T8MxMO3M2qg=="], - "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.2.14", "", { "os": "linux", "cpu": "x64" }, "sha512-Lvqmd92UZ+KZVnr0xU0jYj4XqnCSsBQJHS/FpYkJgZSAN7/4NmPlgMvQXIGW8a3BcFaGRKe8LuGpqM2E4oaX0Q=="], + "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.2.16", "", { "os": "linux", "cpu": "x64" }, "sha512-KgQBGjiucw4e7gM+R8qOzHWBFhjCY1IfCrGjW3Wzxv2hKUlL+mPhelaeJwnEqtNxMUdVTYjlwlu3IHxslXMJWQ=="], - "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.2.14", "", { "os": "win32", "cpu": "arm64" }, "sha512-Jnuud29daaEoZNEp80dxUDLyUcwLr+g6SruHPyyWerOe7J10JE1ihJNkDlXLT7T49xdBGYRQlRkuNGwRfZWx5A=="], + "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.2.16", "", { "os": "win32", "cpu": "arm64" }, "sha512-C6WqEI3VkXatXraMgSFXZjEXq0pzURGjRpFAJZYmuVDmpqE57o7E80Np2UkdZ6m5kpJDt4mRyu3krc/P825iNQ=="], - "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.2.14", "", { "os": "win32", "cpu": "x64" }, "sha512-2ZUNh7yaAMUwAOK8oFEO28qXqPFrWPGGD0KHK1Gp97Th9XuVZniMLtbkbrFtDRh15+PVj7MyrG0N967W7rLr1A=="], + "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.2.16", "", { "os": "win32", "cpu": "x64" }, "sha512-kCX3CMTns6DMCFDNTDV4sjmBKyA/iEvzaVhl/jYi4JRIVT2zcy1lo+lhXT5mPgYHmJZu8Uye6j3Zi3c7Z2Me5A=="], - "@opentui/keymap": ["@opentui/keymap@0.2.14", "", { "dependencies": { "@opentui/core": "0.2.14" }, "peerDependencies": { "@opentui/react": "0.2.14", "@opentui/solid": "0.2.14", "react": ">=19.2.0", "solid-js": "1.9.12" }, "optionalPeers": ["@opentui/react", "@opentui/solid", "react", "solid-js"] }, "sha512-Jd4F3S98D8bJcr41jk7KcsFwwQTA0GCNKb+LoDMkPwv00k+NV6XcrXPB3QlNeM/JrVbe55pyGaT/ynZklGYHRw=="], + "@opentui/keymap": ["@opentui/keymap@0.2.16", "", { "dependencies": { "@opentui/core": "0.2.16" }, "peerDependencies": { "@opentui/react": "0.2.16", "@opentui/solid": "0.2.16", "react": ">=19.2.0", "solid-js": "1.9.12" }, "optionalPeers": ["@opentui/react", "@opentui/solid", "react", "solid-js"] }, "sha512-YBLQfNLbU2kx49bjEY9rrFoNlvIoi5qNJfRcOt6frvnR3C6MLl0/8hZY+vMQ2PEQWeEiNejFnl1lQw+z4Nk2FQ=="], - "@opentui/solid": ["@opentui/solid@0.2.14", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.2.14", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.12", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.12" } }, "sha512-tSWiiwdh/J+crkjwHgd26HXAlJHYocwkN/eUoqSH3+Y/uO3c3qRnbzQz7zzds+j4XDQU/8e9QcZshYLvQT9c7w=="], + "@opentui/solid": ["@opentui/solid@0.2.16", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.2.16", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.12", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.12" } }, "sha512-2Q+v1PPpXXr+sALi9Aj6I5Jvo7xDfbmstYjRLL7lW3Hghh9i7ONQKpt/gyDDRbhSsYrhxKYTNenF9OxgoXkTHg=="], "@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="], @@ -2150,7 +2277,7 @@ "@solid-primitives/rootless": ["@solid-primitives/rootless@1.5.3", "", { "dependencies": { "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-N8cIDAHbWcLahNRLr0knAAQvXyEdEMoAZvIMZKmhNb1mlx9e2UOv9BRD5YNwQUJwbNoYVhhLwFOEOcVXFx0HqA=="], - "@solid-primitives/scheduled": ["@solid-primitives/scheduled@1.5.2", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-/j2igE0xyNaHhj6kMfcUQn5rAVSTLbAX+CDEBm25hSNBmNiHLu2lM7Usj2kJJ5j36D67bE8wR1hBNA8hjtvsQA=="], + "@solid-primitives/scheduled": ["@solid-primitives/scheduled@1.5.3", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-oNwLE6E6lxJAWrc8QXuwM0k2oU1BnANnkChwMw82aK1j3+mWGJkG1IFe5gCwbV+afYmjI76t9JJV3md/8tLw+g=="], "@solid-primitives/scroll": ["@solid-primitives/scroll@2.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/rootless": "^1.5.2", "@solid-primitives/static-store": "^0.1.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-Ejq/Z7zKo/6eIEFr1bFLzXFxiGBCMLuqCM8QB8urr3YdPzjSETFLzYRWUyRiDWaBQN0F7k0SY6S7ig5nWOP7vg=="], @@ -2296,6 +2423,10 @@ "@types/cross-spawn": ["@types/cross-spawn@6.0.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA=="], + "@types/d3-scale": ["@types/d3-scale@4.0.9", "", { "dependencies": { "@types/d3-time": "*" } }, "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="], + + "@types/d3-time": ["@types/d3-time@3.0.4", "", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="], + "@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="], "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], @@ -2440,6 +2571,8 @@ "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], + "@upstash/redis": ["@upstash/redis@1.38.0", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-wu+dZBptlLy0+MCUEoHmzrY/TnmgDey3+c7EbIGwrLqAvkP8yi5MWZHYGIFtAygmL4Bkz2TdFu+eU0vFPncIcg=="], + "@valibot/to-json-schema": ["@valibot/to-json-schema@1.6.0", "", { "peerDependencies": { "valibot": "^1.3.0" } }, "sha512-d6rYyK5KVa2XdqamWgZ4/Nr+cXhxjy7lmpe6Iajw15J/jmU+gyxl2IEd1Otg1d7Rl3gOQL5reulnSypzBtYy1A=="], "@vercel/oidc": ["@vercel/oidc@3.2.0", "", {}, "sha512-UycprH3T6n3jH0k44NHMa7pnFHGu/N05MjojYr+Mc6I7obkoLIJujSWwin1pCvdy/eOxrI/l3uDLQsmcrOb4ug=="], @@ -2592,8 +2725,6 @@ "avvio": ["avvio@9.2.0", "", { "dependencies": { "@fastify/error": "^4.0.0", "fastq": "^1.17.1" } }, "sha512-2t/sy01ArdHHE0vRH5Hsay+RtCZt3dLPji7W7/MMOCEgze5b7SNDC4j5H6FnVgPkI1MTNFGzHdHrVXDDl7QSSQ=="], - "aws-sdk": ["aws-sdk@2.1692.0", "", { "dependencies": { "buffer": "4.9.2", "events": "1.1.1", "ieee754": "1.1.13", "jmespath": "0.16.0", "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", "util": "^0.12.4", "uuid": "8.0.0", "xml2js": "0.6.2" } }, "sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw=="], - "aws-ssl-profiles": ["aws-ssl-profiles@1.1.2", "", {}, "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g=="], "aws4fetch": ["aws4fetch@1.0.20", "", {}, "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g=="], @@ -2678,7 +2809,7 @@ "browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="], - "buffer": ["buffer@4.9.2", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg=="], + "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], "buffer-crc32": ["buffer-crc32@1.0.0", "", {}, "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w=="], @@ -2868,6 +2999,20 @@ "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + "d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], + + "d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="], + + "d3-format": ["d3-format@3.1.2", "", {}, "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg=="], + + "d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="], + + "d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="], + + "d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="], + + "d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="], + "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="], @@ -2974,9 +3119,9 @@ "dotenv-expand": ["dotenv-expand@11.0.7", "", { "dependencies": { "dotenv": "^16.4.5" } }, "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA=="], - "drizzle-kit": ["drizzle-kit@1.0.0-beta.19-d95b7a4", "", { "dependencies": { "@drizzle-team/brocli": "^0.11.0", "@js-temporal/polyfill": "^0.5.1", "esbuild": "^0.25.10", "get-tsconfig": "^4.13.6", "jiti": "^2.6.1" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-M0sqc+42TYBod6kEZ3AsW6+JWe3+76gR1aDFbHH5DmuLKEwewmbzlhBG6qnvV6YA1cIIbkuam3dC7r6PREOCXw=="], + "drizzle-kit": ["drizzle-kit@1.0.0-rc.2", "", { "dependencies": { "@drizzle-team/brocli": "^0.11.0", "@js-temporal/polyfill": "^0.5.1", "esbuild": "^0.25.10", "get-tsconfig": "^4.13.6", "jiti": "^2.6.1" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-TRxUmj1wDA2QCt3GvuhfamvIa66wJ7+MzSxBMKkpRtYScjHTumT9BE+x6daSzuEacSrPEuUH5/cW1uo5RkoPIg=="], - "drizzle-orm": ["drizzle-orm@1.0.0-beta.19-d95b7a4", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@effect/sql": "^0.48.5", "@effect/sql-pg": "^0.49.7", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@sinclair/typebox": ">=0.34.8", "@sqlitecloud/drivers": ">=1.0.653", "@tidbcloud/serverless": "*", "@tursodatabase/database": ">=0.2.1", "@tursodatabase/database-common": ">=0.2.1", "@tursodatabase/database-wasm": ">=0.2.1", "@types/better-sqlite3": "*", "@types/mssql": "^9.1.4", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "arktype": ">=2.0.0", "better-sqlite3": ">=9.3.0", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "mssql": "^11.0.1", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5", "typebox": ">=1.0.0", "valibot": ">=1.0.0-beta.7", "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@effect/sql", "@effect/sql-pg", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@sinclair/typebox", "@sqlitecloud/drivers", "@tidbcloud/serverless", "@tursodatabase/database", "@tursodatabase/database-common", "@tursodatabase/database-wasm", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "arktype", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "mysql2", "pg", "postgres", "sql.js", "sqlite3", "typebox", "valibot", "zod"] }, "sha512-bZZKKeoRKrMVU6zKTscjrSH0+WNb1WEi3N0Jl4wEyQ7aQpTgHzdYY6IJQ1P0M74HuSJVeX4UpkFB/S6dtqLEJg=="], + "drizzle-orm": ["drizzle-orm@1.0.0-rc.2", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@effect/sql-pg": ">=4.0.0-beta.58 || >=4.0.0", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@sinclair/typebox": ">=0.34.8", "@sqlitecloud/drivers": ">=1.0.653", "@tidbcloud/serverless": "*", "@tursodatabase/database": ">=0.2.1", "@tursodatabase/database-common": ">=0.2.1", "@tursodatabase/database-wasm": ">=0.2.1", "@types/better-sqlite3": "*", "@types/mssql": "^9.1.4", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "arktype": ">=2.0.0", "better-sqlite3": ">=9.3.0", "bun-types": "*", "effect": ">=4.0.0-beta.58 || >=4.0.0", "expo-sqlite": ">=14.0.0", "mssql": "^11.0.1", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5", "typebox": ">=1.0.0", "valibot": ">=1.0.0-beta.7", "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@effect/sql-pg", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@sinclair/typebox", "@sqlitecloud/drivers", "@tidbcloud/serverless", "@tursodatabase/database", "@tursodatabase/database-common", "@tursodatabase/database-wasm", "@types/better-sqlite3", "@types/mssql", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "arktype", "better-sqlite3", "bun-types", "effect", "expo-sqlite", "mssql", "mysql2", "pg", "postgres", "sql.js", "sqlite3", "typebox", "valibot", "zod"] }, "sha512-UXYDkbplF5wX0hwxll+80QhEwUvAJLBu+tAK/d4fna18kLE6VuliAzufF/ieDEIJeSnLRYgtmsXD6x1Xuy1kIg=="], "dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="], @@ -2990,7 +3135,7 @@ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - "effect": ["effect@4.0.0-beta.65", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.6.0", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.9", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^13.0.0", "yaml": "^2.8.3" } }, "sha512-QYKvQPAj3CmtsvWkHQww15wX4KG2gNsszDWEcOO5sZCMknp66u6Si/Opmt3wwWCwsyvRmDAdIg+JIz5qzbbFIw=="], + "effect": ["effect@4.0.0-beta.66", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.6.0", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.9", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^13.0.0", "yaml": "^2.8.3" } }, "sha512-4arEr62cziFa8BBVDUwJCJJmaVepXf/kRg7KtC0h8+bufngscrHbwWFhr9c+HonwOF+31U3iD3xUJmw9KzX7Dw=="], "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="], @@ -3274,7 +3419,7 @@ "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], - "gitlab-ai-provider": ["gitlab-ai-provider@6.6.0", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=3.0.0", "@ai-sdk/provider-utils": ">=4.0.0" } }, "sha512-jUxYnKA4XQaPc3wxACDZ8bPDXO0Mzx7cZaBDxbT2uGgLqtGZmSi+9tVNIg7louSS+s/ioVra3SoUz3iOFVhKPA=="], + "gitlab-ai-provider": ["gitlab-ai-provider@6.7.0", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=3.0.0", "@ai-sdk/provider-utils": ">=4.0.0" } }, "sha512-J7apROAmDwDJcLPcbQ9YQiPhyFN1Vvt/f3ugsePaUnzh3sedfHCHGETgG0Mm0dJCB2rC7DYwmV/sgxLQcQ/sjw=="], "glob": ["glob@13.0.5", "", { "dependencies": { "minimatch": "^10.2.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw=="], @@ -3416,7 +3561,7 @@ "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], - "ieee754": ["ieee754@1.1.13", "", {}, "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="], + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], "ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], @@ -3442,6 +3587,8 @@ "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], + "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="], + "ioredis": ["ioredis@5.10.1", "", { "dependencies": { "@ioredis/commands": "1.5.1", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-HuEDBTI70aYdx1v6U97SbNx9F1+svQKBDo30o0b9fw055LMepzpOOd0Ccg9Q6tbqmBSJaMuY0fB7yw9/vjBYCA=="], "ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="], @@ -3548,7 +3695,7 @@ "is64bit": ["is64bit@2.0.0", "", { "dependencies": { "system-architecture": "^0.1.0" } }, "sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw=="], - "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], + "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], "isbinaryfile": ["isbinaryfile@5.0.7", "", {}, "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ=="], @@ -3566,8 +3713,6 @@ "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], - "jmespath": ["jmespath@0.16.0", "", {}, "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw=="], - "jose": ["jose@6.0.11", "", {}, "sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg=="], "js-base64": ["js-base64@3.7.7", "", {}, "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw=="], @@ -4054,8 +4199,6 @@ "opencode-poe-auth": ["opencode-poe-auth@0.0.1", "", { "dependencies": { "open": "^10.0.0", "poe-oauth": "*" }, "peerDependencies": { "@opencode-ai/plugin": "*" } }, "sha512-cXqTlS6AXHzo1oBdosnxbT47ZJEZ9WXn050X8Re6wZ1vaNnTpB/l2fMQt90evT7RBK0fB8UjXQUDMKyd7bbiqg=="], - "opencontrol": ["opencontrol@0.0.6", "", { "dependencies": { "@modelcontextprotocol/sdk": "1.6.1", "@tsconfig/bun": "1.0.7", "hono": "4.7.4", "zod": "3.24.2", "zod-to-json-schema": "3.24.3" }, "bin": { "opencontrol": "bin/index.mjs" } }, "sha512-QeCrpOK5D15QV8kjnGVeD/BHFLwcVr+sn4T6KKmP0WAMs2pww56e4h+eOGHb5iPOufUQXbdbBKi6WV2kk7tefQ=="], - "openid-client": ["openid-client@5.6.4", "", { "dependencies": { "jose": "^4.15.4", "lru-cache": "^6.0.0", "object-hash": "^2.2.0", "oidc-token-hash": "^5.0.3" } }, "sha512-T1h3B10BRPKfcObdBklX639tVz+xh34O7GjofqrqiAQdm7eHsQ00ih18x6wuJ/E6FxdtS2u3FmUGPDeEcMwzNA=="], "opentui-spinner": ["opentui-spinner@0.0.6", "", { "dependencies": { "cli-spinners": "^3.3.0" }, "peerDependencies": { "@opentui/core": "^0.1.49", "@opentui/react": "^0.1.49", "@opentui/solid": "^0.1.49", "typescript": "^5" }, "optionalPeers": ["@opentui/react", "@opentui/solid"] }, "sha512-xupLOeVQEAXEvVJCvHkfX6fChDWmJIPHe5jyUrVb8+n4XVTX8mBNhitFfB9v2ZbkC1H2UwPab/ElePHoW37NcA=="], @@ -4252,7 +4395,7 @@ "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], - "punycode": ["punycode@1.3.2", "", {}, "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="], + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "pupa": ["pupa@3.3.0", "", { "dependencies": { "escape-goat": "^4.0.0" } }, "sha512-LjgDO2zPtoXP2wJpDjZrGdojii1uqO0cnwKoIoUzkfS98HDmbeiGmYiXo3lXeFlq2xvne1QFQhwYXSUCLKtEuA=="], @@ -4262,8 +4405,6 @@ "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], - "querystring": ["querystring@0.2.0", "", {}, "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g=="], - "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], "quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="], @@ -4448,7 +4589,7 @@ "sanitize-filename": ["sanitize-filename@1.6.4", "", { "dependencies": { "truncate-utf8-bytes": "^1.0.0" } }, "sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg=="], - "sax": ["sax@1.2.1", "", {}, "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA=="], + "sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], "scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], @@ -4576,23 +4717,23 @@ "ssri": ["ssri@13.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ=="], - "sst": ["sst@3.18.10", "", { "dependencies": { "aws-sdk": "2.1692.0", "aws4fetch": "1.0.18", "jose": "5.2.3", "opencontrol": "0.0.6", "openid-client": "5.6.4" }, "optionalDependencies": { "sst-darwin-arm64": "3.18.10", "sst-darwin-x64": "3.18.10", "sst-linux-arm64": "3.18.10", "sst-linux-x64": "3.18.10", "sst-linux-x86": "3.18.10", "sst-win32-arm64": "3.18.10", "sst-win32-x64": "3.18.10", "sst-win32-x86": "3.18.10" }, "bin": { "sst": "bin/sst.mjs" } }, "sha512-SY+ldeJ9K5E9q+DhjXA3e2W3BEOzBwkE3IyLSD71uA3/5nRhUAST31iOWEpW36LbIvSQ9uOVDFcebztoLJ8s7w=="], + "sst": ["sst@4.13.1", "", { "dependencies": { "@aws/durable-execution-sdk-js": "1.0.2", "aws4fetch": "1.0.18", "jose": "5.2.3", "openid-client": "5.6.4" }, "optionalDependencies": { "sst-darwin-arm64": "4.13.1", "sst-darwin-x64": "4.13.1", "sst-linux-arm64": "4.13.1", "sst-linux-x64": "4.13.1", "sst-linux-x86": "4.13.1", "sst-win32-arm64": "4.13.1", "sst-win32-x64": "4.13.1", "sst-win32-x86": "4.13.1" }, "bin": { "sst": "bin/sst.mjs" } }, "sha512-FKzhWuqV5NPhFWH7b+Ktf5+Mvox6DCMc8iOrjaS3mkjnnmyEcOZq7HNx2/ZlIcBwgOZE9sCPR3ot1zXtXkXzZg=="], - "sst-darwin-arm64": ["sst-darwin-arm64@3.18.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3MwIpMZhhdZKDqLp9ZQNlwkWix5+q+N0PWstuTomYwgZOxCCe6u9IIsoIszSk+GAJJN/jvGZyLiXKeV4iiQvw=="], + "sst-darwin-arm64": ["sst-darwin-arm64@4.13.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gGwfgZGOsulU6iGeZJtxP5BpSZFsRUy1dG/yTqJa++n1P1APWXZC64u2qRHm6rdwLAjEeWaCQ9k7ouKgn0zh5Q=="], - "sst-darwin-x64": ["sst-darwin-x64@3.18.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-nQ0jMKkPOa+kj6Ygz8+kYhBua/vgNTLkd+4r8NSmk7v+Zs78lKnx3T//kEzS0yik6Q6QwGfokwrTcA1Jii2xSw=="], + "sst-darwin-x64": ["sst-darwin-x64@4.13.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-RcKLI2oAY+Wk5fWUF0gJFKvwMSpid3qw9L3OcfgFL2ymZH652ybLpQPBxtoJ95FdyknWIMnYf6ZK9C2jnH5eaw=="], - "sst-linux-arm64": ["sst-linux-arm64@3.18.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-mj9VNj3SvLS+HaXx2PhCX0aTA7CwJNoM6JhRc0s/zCilqchcvqDjbhpYBJO4brEPv6aOaaa7T3WvIQqtYauK4Q=="], + "sst-linux-arm64": ["sst-linux-arm64@4.13.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Lp/8BWhH8KZnb50xPd8A6bkZ7QqCH3Dar9l16TPwuAmPxxRUlkmg42h+ACZ9n02vSJl8y/WLnV4JB6SgJpRFVg=="], - "sst-linux-x64": ["sst-linux-x64@3.18.10", "", { "os": "linux", "cpu": "x64" }, "sha512-7iy1Eq2eqnT9Ag/8OVgC04vRjV7AAQyf/BvzLc+6Sz+GvRiKA8VEuPnbXNYQF+NIvEqsawfcd7MknSTtImpsvQ=="], + "sst-linux-x64": ["sst-linux-x64@4.13.1", "", { "os": "linux", "cpu": "x64" }, "sha512-f4eHOsApoP+CpUzLUGzfoTBYsqqr6nl/M0gjYsVNi1T+6v92lc84AhQ4DoDZx033QggyxkqRezj8jOkjkKxa7w=="], - "sst-linux-x86": ["sst-linux-x86@3.18.10", "", { "os": "linux", "cpu": "none" }, "sha512-77qZSuPZeQ5bdRCiq1pQEdY8EcGNHboKrx4P2yFid2FBDKJsXxOXtIxJdloyx+ljBn0+nxl/g040QBmXxdc9tA=="], + "sst-linux-x86": ["sst-linux-x86@4.13.1", "", { "os": "linux", "cpu": "none" }, "sha512-5OHdtPa0GmozDpBPdsD9Tv+SGnpjJSoTXptgK59ivQg3UYNWBBotidvEyUJs1MU9B/3+I+Fmw32zsF2O+ZtPgg=="], - "sst-win32-arm64": ["sst-win32-arm64@3.18.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-aY+FhMxvYs8crlrKALpLn/kKmud8YQj6LkMHsrOAAIJhfNyxhCja2vrYQaY+bcqdsS5W2LMVcS2hyaMqKXZKcg=="], + "sst-win32-arm64": ["sst-win32-arm64@4.13.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-qAUuCQj6wDdZ84a9W4FhnRTHYlEnYRHGYFqO3cmMImbnAQEoKSQR1XuWqt0Ev4RT3kU4Lz/fgvJjGkR7WUstLg=="], - "sst-win32-x64": ["sst-win32-x64@3.18.10", "", { "os": "win32", "cpu": "x64" }, "sha512-rY+yJXOpG+P5xXnaQRpCvBK2zwwLhjzpYidGkp6F+cGgiVdh2Wre/CIQNRaVHr20ncj8lLe/RsHWa9QCNM48jg=="], + "sst-win32-x64": ["sst-win32-x64@4.13.1", "", { "os": "win32", "cpu": "x64" }, "sha512-r+83NMwpe4MLAvkVoOxi1KNs6nIqilFucsTr+VN1PgknsiVBY1emITjSWS2jDJJMuH8xJXL5xJzF/l5rcKWErg=="], - "sst-win32-x86": ["sst-win32-x86@3.18.10", "", { "os": "win32", "cpu": "none" }, "sha512-pq8SmV0pIjBFMY6DraUZ4akyTxHnfjIKCRbBLdMxFUZK8TzA1NK2YdjRt1AwrgXRYGRyctrz/mt4WyO0SMOVQQ=="], + "sst-win32-x86": ["sst-win32-x86@4.13.1", "", { "os": "win32", "cpu": "none" }, "sha512-YPxBVdac/MsrzwlC6pF0NrrvMcmfdBLYjv7MbzHc5jNh1FQ1WPh6bdWQqgv0KD9EQTNLLEkej0beydgUvcCWJg=="], "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], @@ -4872,8 +5013,6 @@ "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], - "url": ["url@0.10.3", "", { "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" } }, "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ=="], - "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], @@ -4882,8 +5021,6 @@ "utf8-byte-length": ["utf8-byte-length@1.0.5", "", {}, "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA=="], - "util": ["util@0.12.5", "", { "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", "which-typed-array": "^1.1.2" } }, "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA=="], - "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], @@ -4896,7 +5033,7 @@ "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], - "venice-ai-sdk-provider": ["venice-ai-sdk-provider@2.0.1", "", { "dependencies": { "@ai-sdk/openai-compatible": "^2.0.37", "@ai-sdk/provider": "^3.0.8", "@ai-sdk/provider-utils": "^4.0.21" }, "peerDependencies": { "ai": "^6.0.90" } }, "sha512-6SxA8a4MoA6Q/c+D3q7My0Hfog76enN3n0MXhwosM+tso66rXBEGeBRD/0lravRDVzL2Q1w5QJPc86rAVJtfXg=="], + "venice-ai-sdk-provider": ["venice-ai-sdk-provider@2.0.2", "", { "dependencies": { "@ai-sdk/openai-compatible": "^2.0.47", "@ai-sdk/provider": "^3.0.10", "@ai-sdk/provider-utils": "^4.0.27" }, "peerDependencies": { "ai": "^6.0.90" } }, "sha512-aoa05nI3BTK5aGbjBflq+Gfln2AHAkwNbWuGGvCzUIsOfp5Y3iPD4O4PUGDAEiWVJWbjpPn0KfDa0H/HebwsaA=="], "verror": ["verror@1.10.1", "", { "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg=="], @@ -5004,12 +5141,14 @@ "write-file-atomic": ["write-file-atomic@7.0.1", "", { "dependencies": { "signal-exit": "^4.0.1" } }, "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg=="], - "ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], "wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="], "xdg-basedir": ["xdg-basedir@5.1.0", "", {}, "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ=="], + "xml-naming": ["xml-naming@0.1.0", "", {}, "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw=="], + "xml2js": ["xml2js@0.6.2", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA=="], "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], @@ -5072,9 +5211,13 @@ "@ai-sdk/alibaba/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], - "@ai-sdk/amazon-bedrock/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.71", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bUWOzrzR0gJKJO/PLGMR4uH2dqEgqGhrsCV+sSpk4KtOEnUQlfjZI/F7BFlqSvVpFbjdgYRRLysAeEZpJ6S1lg=="], + "@ai-sdk/amazon-bedrock/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.78", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-0OY12G20cUt6iU6htpEA1491Oz++NVxZxlmWGX4B7rSbeZ5pnDmOu6YtW9BKzdZlNx5Gn23i6WMxyZFoMKNcgA=="], - "@ai-sdk/amazon-bedrock/@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.13", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.0", "@smithy/util-hex-encoding": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-vYahwBAtRaAcFbOmE9aLr12z7RiHYDSLcnogSdxfm7kKfsNa3wH+NU5r7vTeB5rKvLsWyPjVX8iH94brP7umiQ=="], + "@ai-sdk/amazon-bedrock/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], + + "@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], + + "@ai-sdk/amazon-bedrock/@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.14", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.1", "@smithy/util-hex-encoding": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-erZq0nOIpzfeZdCyzZjdJb4nVSKLUmSkaQUVkRGQTXs30gyUGeKnrYEg+Xe1W5gE3aReS7IgsvANwVPxSzY6Pw=="], "@ai-sdk/amazon-bedrock/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], @@ -5090,11 +5233,17 @@ "@ai-sdk/fireworks/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], - "@ai-sdk/google-vertex/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.71", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bUWOzrzR0gJKJO/PLGMR4uH2dqEgqGhrsCV+sSpk4KtOEnUQlfjZI/F7BFlqSvVpFbjdgYRRLysAeEZpJ6S1lg=="], + "@ai-sdk/google/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], + + "@ai-sdk/google/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], - "@ai-sdk/google-vertex/@ai-sdk/google": ["@ai-sdk/google@3.0.64", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-CbR82EgGPNrj/6q0HtclwuCqe0/pDShyv3nWDP/A9DroujzWXnLMlUJVrgPOsg4b40zQCwwVs2XSKCxvt/4QaA=="], + "@ai-sdk/google-vertex/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.77", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ML8C2M1YvPA1ulEx4TiyF0k1xvC2ikEiPBIC1PPQ0a5xELUGrO2lAaEzsTEoJ+eCeDd8PSBuFJjs+r+9yIwQXA=="], - "@ai-sdk/google-vertex/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], + "@ai-sdk/google-vertex/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.47", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Enm5UlL0zUCrW3792opk5h7hRWxZOZzDe6eQYVFqX9LUOGGCe1h8MZWAGim765nwzgnjlpeYOsuzZmLtRsTPlg=="], + + "@ai-sdk/google-vertex/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], + + "@ai-sdk/google-vertex/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], "@ai-sdk/groq/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], @@ -5148,6 +5297,16 @@ "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], + "@aws-sdk/client-athena/@smithy/core": ["@smithy/core@3.24.3", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-Ep/7tPamGY8mgESE3LyLKtxJyy6U52WWAqr/3wial47Sj4u3PiIF73AOGI27UyLy9duTkhZbgzodOfLV4TduZg=="], + + "@aws-sdk/client-athena/@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-F+DRf8IJazRJgYog2A/yJK7eYVc0rqTlRzO+5ZxjJd4WkZoKz0IJRncf7G6t1pdVT3kryJcwuTFhN1c5m6N47A=="], + + "@aws-sdk/client-athena/@smithy/node-http-handler": ["@smithy/node-http-handler@4.7.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA=="], + + "@aws-sdk/client-athena/@smithy/types": ["@smithy/types@4.14.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw=="], + + "@aws-sdk/client-athena/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], + "@aws-sdk/client-cognito-identity/@aws-sdk/core": ["@aws-sdk/core@3.973.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.7", "@aws-sdk/xml-builder": "^3.972.17", "@smithy/core": "^3.23.14", "@smithy/node-config-provider": "^4.3.13", "@smithy/property-provider": "^4.2.13", "@smithy/protocol-http": "^5.3.13", "@smithy/signature-v4": "^5.3.13", "@smithy/smithy-client": "^4.12.9", "@smithy/types": "^4.14.0", "@smithy/util-base64": "^4.3.2", "@smithy/util-middleware": "^4.2.13", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-CUZ5m8hwMCH6OYI4Li/WgMfIEx10Q2PLI9Y3XOUTPGZJ53aZ0007jCv+X/ywsaERyKPdw5MRZWk877roQksQ4A=="], "@aws-sdk/client-cognito-identity/@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.30", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.25", "@aws-sdk/credential-provider-http": "^3.972.27", "@aws-sdk/credential-provider-ini": "^3.972.29", "@aws-sdk/credential-provider-process": "^3.972.25", "@aws-sdk/credential-provider-sso": "^3.972.29", "@aws-sdk/credential-provider-web-identity": "^3.972.29", "@aws-sdk/types": "^3.973.7", "@smithy/credential-provider-imds": "^4.2.13", "@smithy/property-provider": "^4.2.13", "@smithy/shared-ini-file-loader": "^4.4.8", "@smithy/types": "^4.14.0", "tslib": "^2.6.2" } }, "sha512-FMnAnWxc8PG+ZrZ2OBKzY4luCUJhe9CG0B9YwYr4pzrYGLXBS2rl+UoUvjGbAwiptxRL6hyA3lFn03Bv1TLqTw=="], @@ -5172,6 +5331,30 @@ "@aws-sdk/client-cognito-identity/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], + "@aws-sdk/client-firehose/@smithy/core": ["@smithy/core@3.24.3", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-Ep/7tPamGY8mgESE3LyLKtxJyy6U52WWAqr/3wial47Sj4u3PiIF73AOGI27UyLy9duTkhZbgzodOfLV4TduZg=="], + + "@aws-sdk/client-firehose/@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-F+DRf8IJazRJgYog2A/yJK7eYVc0rqTlRzO+5ZxjJd4WkZoKz0IJRncf7G6t1pdVT3kryJcwuTFhN1c5m6N47A=="], + + "@aws-sdk/client-firehose/@smithy/node-http-handler": ["@smithy/node-http-handler@4.7.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA=="], + + "@aws-sdk/client-firehose/@smithy/types": ["@smithy/types@4.14.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw=="], + + "@aws-sdk/client-firehose/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], + + "@aws-sdk/client-lambda/@aws-sdk/core": ["@aws-sdk/core@3.974.11", "", { "dependencies": { "@aws-sdk/types": "^3.973.8", "@aws-sdk/xml-builder": "^3.972.24", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.2", "@smithy/signature-v4": "^5.4.2", "@smithy/types": "^4.14.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-QpnINq5FZH6EOaDEkmHdT7eUunbvD27pDNQypaWjFyYz7Zl1q3UCMQErBZxpmfGfI7MvI2TlK8KTkgNpv8b1ug=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.42", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.37", "@aws-sdk/credential-provider-http": "^3.972.39", "@aws-sdk/credential-provider-ini": "^3.972.41", "@aws-sdk/credential-provider-process": "^3.972.37", "@aws-sdk/credential-provider-sso": "^3.972.41", "@aws-sdk/credential-provider-web-identity": "^3.972.41", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/credential-provider-imds": "^4.3.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-D4oon2zbqqsWOJUM99Gm3/ZyJ0IJvTXVN3PyloGb3kQEyI36fjCZheZj422lAgTWWd6TSHgiImLt3RIaLdv3dQ=="], + + "@aws-sdk/client-lambda/@aws-sdk/types": ["@aws-sdk/types@3.973.8", "", { "dependencies": { "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw=="], + + "@aws-sdk/client-lambda/@smithy/core": ["@smithy/core@3.24.3", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-Ep/7tPamGY8mgESE3LyLKtxJyy6U52WWAqr/3wial47Sj4u3PiIF73AOGI27UyLy9duTkhZbgzodOfLV4TduZg=="], + + "@aws-sdk/client-lambda/@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-F+DRf8IJazRJgYog2A/yJK7eYVc0rqTlRzO+5ZxjJd4WkZoKz0IJRncf7G6t1pdVT3kryJcwuTFhN1c5m6N47A=="], + + "@aws-sdk/client-lambda/@smithy/node-http-handler": ["@smithy/node-http-handler@4.7.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA=="], + + "@aws-sdk/client-lambda/@smithy/types": ["@smithy/types@4.14.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg=="], + "@aws-sdk/client-sso/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], "@aws-sdk/client-sts/@aws-sdk/core": ["@aws-sdk/core@3.775.0", "", { "dependencies": { "@aws-sdk/types": "3.775.0", "@smithy/core": "^3.2.0", "@smithy/node-config-provider": "^4.0.2", "@smithy/property-provider": "^4.0.2", "@smithy/protocol-http": "^5.1.0", "@smithy/signature-v4": "^5.0.2", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/util-middleware": "^4.0.2", "fast-xml-parser": "4.4.1", "tslib": "^2.6.2" } }, "sha512-8vpW4WihVfz0DX+7WnnLGm3GuQER++b0IwQG35JlQMlgqnc44M//KbJPsIHA0aJUJVwJAEShgfr5dUbY8WUzaA=="], @@ -5316,6 +5499,8 @@ "@cloudflare/kv-asset-handler/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="], + "@cloudflare/vite-plugin/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], "@develar/schema-utils/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="], @@ -5636,28 +5821,18 @@ "astro/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "aws-sdk/events": ["events@1.1.1", "", {}, "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw=="], - - "aws-sdk/uuid": ["uuid@8.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw=="], - "babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], "babel-plugin-module-resolver/glob": ["glob@9.3.5", "", { "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" } }, "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q=="], - "bl/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], - "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "body-parser/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], "body-parser/qs": ["qs@6.14.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q=="], - "buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], - "builder-util/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "builder-util-runtime/sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], - "c12/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], "c12/dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="], @@ -5678,6 +5853,8 @@ "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + "db0/drizzle-orm": ["drizzle-orm@1.0.0-beta.19-d95b7a4", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@effect/sql": "^0.48.5", "@effect/sql-pg": "^0.49.7", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@sinclair/typebox": ">=0.34.8", "@sqlitecloud/drivers": ">=1.0.653", "@tidbcloud/serverless": "*", "@tursodatabase/database": ">=0.2.1", "@tursodatabase/database-common": ">=0.2.1", "@tursodatabase/database-wasm": ">=0.2.1", "@types/better-sqlite3": "*", "@types/mssql": "^9.1.4", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "arktype": ">=2.0.0", "better-sqlite3": ">=9.3.0", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "mssql": "^11.0.1", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5", "typebox": ">=1.0.0", "valibot": ">=1.0.0-beta.7", "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@effect/sql", "@effect/sql-pg", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@sinclair/typebox", "@sqlitecloud/drivers", "@tidbcloud/serverless", "@tursodatabase/database", "@tursodatabase/database-common", "@tursodatabase/database-wasm", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "arktype", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "mysql2", "pg", "postgres", "sql.js", "sqlite3", "typebox", "valibot", "zod"] }, "sha512-bZZKKeoRKrMVU6zKTscjrSH0+WNb1WEi3N0Jl4wEyQ7aQpTgHzdYY6IJQ1P0M74HuSJVeX4UpkFB/S6dtqLEJg=="], + "defaults/clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="], "dir-compare/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], @@ -5712,8 +5889,6 @@ "engine.io-client/ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="], - "es-get-iterator/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], - "esbuild-plugin-copy/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "esbuild-plugin-copy/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], @@ -5788,6 +5963,8 @@ "miniflare/undici": ["undici@7.14.0", "", {}, "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ=="], + "miniflare/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], "minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], @@ -5816,22 +5993,14 @@ "opencode/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], + "opencode/@solid-primitives/scheduled": ["@solid-primitives/scheduled@1.5.2", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-/j2igE0xyNaHhj6kMfcUQn5rAVSTLbAX+CDEBm25hSNBmNiHLu2lM7Usj2kJJ5j36D67bE8wR1hBNA8hjtvsQA=="], + "opencode/minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="], "opencode-gitlab-auth/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], "opencode-poe-auth/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], - "opencontrol/@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.6.1", "", { "dependencies": { "content-type": "^1.0.5", "cors": "^2.8.5", "eventsource": "^3.0.2", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^4.1.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-oxzMzYCkZHMntzuyerehK3fV6A2Kwh5BD6CGEJSVDU2QNEhfLOptf2X7esQgaHZXHZY0oHmMsOtIDLP71UJXgA=="], - - "opencontrol/@tsconfig/bun": ["@tsconfig/bun@1.0.7", "", {}, "sha512-udGrGJBNQdXGVulehc1aWT73wkR9wdaGBtB6yL70RJsqwW/yJhIg6ZbRlPOfIUiFNrnBuYLBi9CSmMKfDC7dvA=="], - - "opencontrol/hono": ["hono@4.7.4", "", {}, "sha512-Pst8FuGqz3L7tFF+u9Pu70eI0xa5S3LPUmrNd5Jm8nTHze9FxLTK9Kaj5g/k4UcwuJSXTP65SyHOPLrffpcAJg=="], - - "opencontrol/zod": ["zod@3.24.2", "", {}, "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ=="], - - "opencontrol/zod-to-json-schema": ["zod-to-json-schema@3.24.3", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-HIAfWdYIt1sssHfYZFCXp4rU1w2r8hVVXYIlmoa0r0gABLs5di3RCqPU5DDROogVz1pAdYBaz7HK5n9pSUNs3A=="], - "openid-client/jose": ["jose@4.15.9", "", {}, "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA=="], "openid-client/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], @@ -5878,8 +6047,6 @@ "raw-body/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], - "readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], - "readdir-glob/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="], "restore-cursor/onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], @@ -5890,10 +6057,6 @@ "router/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="], - "safe-array-concat/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], - - "safe-push-apply/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], - "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], @@ -5906,8 +6069,6 @@ "shiki/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], - "sitemap/sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], - "slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], "slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@4.0.0", "", {}, "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ=="], @@ -5920,6 +6081,8 @@ "storybook/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], + "storybook/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "storybook-solidjs-vite/vite-plugin-solid": ["vite-plugin-solid@2.11.12", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-FgjPcx2OwX9h6f28jli7A4bG7PP3te8uyakE5iqsmpq3Jqi1TWLgSroC9N6cMfGRU2zXsl4Q6ISvTr2VL0QHpA=="], "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -5950,9 +6113,11 @@ "unused-filename/path-exists": ["path-exists@5.0.0", "", {}, "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ=="], - "uri-js/punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + "venice-ai-sdk-provider/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.47", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Enm5UlL0zUCrW3792opk5h7hRWxZOZzDe6eQYVFqX9LUOGGCe1h8MZWAGim765nwzgnjlpeYOsuzZmLtRsTPlg=="], - "venice-ai-sdk-provider/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], + "venice-ai-sdk-provider/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], + + "venice-ai-sdk-provider/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], "vite-plugin-icons-spritesheet/glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="], @@ -5970,8 +6135,6 @@ "vscode-languageserver-protocol/vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="], - "which-builtin-type/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], - "wrangler/esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="], "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], @@ -5980,8 +6143,6 @@ "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "xml2js/sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], - "yaml-language-server/request-light": ["request-light@0.5.8", "", {}, "sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg=="], "yaml-language-server/yaml": ["yaml@2.7.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ=="], @@ -6002,6 +6163,12 @@ "@actions/github/@octokit/plugin-rest-endpoint-methods/@octokit/types": ["@octokit/types@12.6.0", "", { "dependencies": { "@octokit/openapi-types": "^20.0.0" } }, "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw=="], + "@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + + "@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils/eventsource-parser": ["eventsource-parser@3.0.8", "", {}, "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ=="], + + "@ai-sdk/amazon-bedrock/@smithy/eventstream-codec/@smithy/types": ["@smithy/types@4.14.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg=="], + "@ai-sdk/anthropic/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "@ai-sdk/azure/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], @@ -6012,6 +6179,14 @@ "@ai-sdk/deepinfra/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "@ai-sdk/google-vertex/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + + "@ai-sdk/google-vertex/@ai-sdk/provider-utils/eventsource-parser": ["eventsource-parser@3.0.8", "", {}, "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ=="], + + "@ai-sdk/google/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + + "@ai-sdk/google/@ai-sdk/provider-utils/eventsource-parser": ["eventsource-parser@3.0.8", "", {}, "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ=="], + "@ai-sdk/groq/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "@ai-sdk/mistral/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], @@ -6046,6 +6221,36 @@ "@aws-sdk/client-cognito-identity/@aws-sdk/middleware-user-agent/@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.996.6", "", { "dependencies": { "@aws-sdk/types": "^3.973.7", "@smithy/types": "^4.14.0", "@smithy/url-parser": "^4.2.13", "@smithy/util-endpoints": "^3.3.4", "tslib": "^2.6.2" } }, "sha512-2nUQ+2ih7CShuKHpGSIYvvAIOHy52dOZguYG36zptBukhw6iFwcvGfG0tes0oZFWQqEWvgZe9HLWaNlvXGdOrg=="], + "@aws-sdk/client-lambda/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.24", "", { "dependencies": { "@nodable/entities": "2.1.0", "@smithy/types": "^4.14.1", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-V8z5YcDPfsvzrBlj0xR1vhRtocblhYbqdreCJB/voGd4Sr5zjNAeWxexbnqVtskTJe0vFb5KMqbSL++ePl+zRw=="], + + "@aws-sdk/client-lambda/@aws-sdk/core/@smithy/signature-v4": ["@smithy/signature-v4@5.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-53+75QuPl6DL+ct6vVEB51FDO5oulXr20TPV46VvJZg76lIlXNWfxi8j+G2V/t0I2qxCBOa3vX/8bmjrpFVo9g=="], + + "@aws-sdk/client-lambda/@aws-sdk/core/@smithy/types": ["@smithy/types@4.14.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.37", "", { "dependencies": { "@aws-sdk/core": "^3.974.11", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-/jpPvEh6f7ntmIzf7dNxoNX6Q8vt8UpesCjbW6mFfk4V1NW6bIy9qxcQ6WbA8As5yQhsZOe+xeNd4xHX8kdY2Q=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.39", "", { "dependencies": { "@aws-sdk/core": "^3.974.11", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/fetch-http-handler": "^5.4.2", "@smithy/node-http-handler": "^4.7.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-pIgTpisWyWg7X1bUbzSjuUYosYTD0Ghz2M0hkSTmb3a6i3qV3uU+NYJPI/E2XSC0HcsZh5rsLPzeXrkb2DS0Cg=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.972.41", "", { "dependencies": { "@aws-sdk/core": "^3.974.11", "@aws-sdk/credential-provider-env": "^3.972.37", "@aws-sdk/credential-provider-http": "^3.972.39", "@aws-sdk/credential-provider-login": "^3.972.41", "@aws-sdk/credential-provider-process": "^3.972.37", "@aws-sdk/credential-provider-sso": "^3.972.41", "@aws-sdk/credential-provider-web-identity": "^3.972.41", "@aws-sdk/nested-clients": "^3.997.9", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/credential-provider-imds": "^4.3.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-u2tyjaxJJzW8UtW4SM1ZcPMDwO6y+kV+llvou+Adts0FAKyzes5jG4izQN+KX3yE8ZROpS5y1LJ//xL2iSf76w=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.37", "", { "dependencies": { "@aws-sdk/core": "^3.974.11", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-7nVaHBUaWIddASYfVaA9O4D5ZVjewU3sCol9WqZPGfW0nR+0WqE0xHZnD/U2L33PlOB8KNXGKZ6wOES/QijKzg=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.972.41", "", { "dependencies": { "@aws-sdk/core": "^3.974.11", "@aws-sdk/nested-clients": "^3.997.9", "@aws-sdk/token-providers": "3.1048.0", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-IOWAWEHe5LkjSKkkUUX9ciV6Y1scHTsnfEkdt5yyC4Slrc7AGbkLPrpntjqh18ksJAMOaVhoBsO8p2WyTcY2wQ=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.41", "", { "dependencies": { "@aws-sdk/core": "^3.974.11", "@aws-sdk/nested-clients": "^3.997.9", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-mbACk9Yypa8nm4iGZLs0PofOXEcTDOUw6wDnsPXNDNSd2WNXs1tSo+6nc/fh0jLYdfVZThhBL98PHW4aXFsG5A=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.3.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-I2Bti0DKFo2IJyN28ijCsx51BAumEYR4/1yZ1FXyBygy9MqbnMqCev4JPth/MbpRfBSRAX35hITSnAdJRo1u5w=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@smithy/types": ["@smithy/types@4.14.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw=="], + + "@aws-sdk/client-lambda/@aws-sdk/types/@smithy/types": ["@smithy/types@4.14.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw=="], + + "@aws-sdk/client-lambda/@smithy/core/@smithy/types": ["@smithy/types@4.14.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw=="], + + "@aws-sdk/client-lambda/@smithy/fetch-http-handler/@smithy/types": ["@smithy/types@4.14.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw=="], + + "@aws-sdk/client-lambda/@smithy/node-http-handler/@smithy/types": ["@smithy/types@4.14.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw=="], + "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.775.0", "", { "dependencies": { "@aws-sdk/core": "3.775.0", "@aws-sdk/types": "3.775.0", "@smithy/property-provider": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-6ESVxwCbGm7WZ17kY1fjmxQud43vzJFoLd4bmlR+idQSWdqlzGDYdcfzpjDKTcivdtNrVYmFvcH1JBUwCRAZhw=="], "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.775.0", "", { "dependencies": { "@aws-sdk/core": "3.775.0", "@aws-sdk/types": "3.775.0", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/property-provider": "^4.0.2", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/util-stream": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-PjDQeDH/J1S0yWV32wCj2k5liRo0ssXMseCBEkCsD3SqsU8o5cU82b0hMX4sAib/RkglCSZqGO0xMiN0/7ndww=="], @@ -6216,8 +6421,6 @@ "@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.2.3", "", {}, "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg=="], - "@azure/core-http/xml2js/sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], - "@azure/core-xml/fast-xml-parser/strnum": ["strnum@2.2.3", "", {}, "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg=="], "@azure/identity/open/wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], @@ -6530,14 +6733,10 @@ "babel-plugin-module-resolver/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - "bl/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], - "body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "c12/chokidar/readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], - "crc/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], - "cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], "dir-compare/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], @@ -6580,6 +6779,8 @@ "lazystream/readable-stream/core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], + "lazystream/readable-stream/isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], + "lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], "lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], @@ -6594,18 +6795,6 @@ "opencode-poe-auth/open/wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], - "opencontrol/@modelcontextprotocol/sdk/express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="], - - "opencontrol/@modelcontextprotocol/sdk/express-rate-limit": ["express-rate-limit@7.5.1", "", { "peerDependencies": { "express": ">= 4.11" } }, "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw=="], - - "opencontrol/@modelcontextprotocol/sdk/pkce-challenge": ["pkce-challenge@4.1.0", "", {}, "sha512-ZBmhE1C9LcPoH9XZSdwiPtbPHZROwAnMy+kIFQVrnMCxY4Cudlz3gBOpzilgc0jOgRaiT3sIWfpMomW2ar2orQ=="], - - "opencontrol/@modelcontextprotocol/sdk/raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="], - - "opencontrol/@modelcontextprotocol/sdk/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "opencontrol/@modelcontextprotocol/sdk/zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], - "ora/bl/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], "ora/bl/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], @@ -6618,8 +6807,6 @@ "pkg-up/find-up/locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], - "readable-stream/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], - "readdir-glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], "restore-cursor/onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], @@ -6646,6 +6833,10 @@ "unplugin/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + "venice-ai-sdk-provider/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + + "venice-ai-sdk-provider/@ai-sdk/provider-utils/eventsource-parser": ["eventsource-parser@3.0.8", "", {}, "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ=="], + "vitest/@vitest/expect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "vitest/@vitest/expect/chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], @@ -6738,6 +6929,18 @@ "@aws-sdk/client-cognito-identity/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.5.8", "", { "dependencies": { "fast-xml-builder": "^1.1.4", "path-expression-matcher": "^1.2.0", "strnum": "^2.2.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ=="], + "@aws-sdk/client-lambda/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini/@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.41", "", { "dependencies": { "@aws-sdk/core": "^3.974.11", "@aws-sdk/nested-clients": "^3.997.9", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-0LBitxXiAiaE5nlFPfpNIww/8FRY/I7WIndWsc9GmNFOM7cE1wNpVNQEGEk9Outg5l8xl+3vybxFyUy4l9q/LQ=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.9", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.11", "@aws-sdk/signature-v4-multi-region": "^3.996.27", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/fetch-http-handler": "^5.4.2", "@smithy/node-http-handler": "^4.7.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-jPR3rnmRI4hWYyzfmTGBr7NblMp8QYYeflHXba1H6+7CGrWVqWKQzaXFQ4qbExqPRsXN3T3L3JxFhr6aouXUGQ=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.9", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.11", "@aws-sdk/signature-v4-multi-region": "^3.996.27", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/fetch-http-handler": "^5.4.2", "@smithy/node-http-handler": "^4.7.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-jPR3rnmRI4hWYyzfmTGBr7NblMp8QYYeflHXba1H6+7CGrWVqWKQzaXFQ4qbExqPRsXN3T3L3JxFhr6aouXUGQ=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1048.0", "", { "dependencies": { "@aws-sdk/core": "^3.974.11", "@aws-sdk/nested-clients": "^3.997.9", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.9", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.11", "@aws-sdk/signature-v4-multi-region": "^3.996.27", "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/fetch-http-handler": "^5.4.2", "@smithy/node-http-handler": "^4.7.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-jPR3rnmRI4hWYyzfmTGBr7NblMp8QYYeflHXba1H6+7CGrWVqWKQzaXFQ4qbExqPRsXN3T3L3JxFhr6aouXUGQ=="], + "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.782.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/hash-node": "^4.0.2", "@smithy/invalid-dependency": "^4.0.2", "@smithy/middleware-content-length": "^4.0.2", "@smithy/middleware-endpoint": "^4.1.0", "@smithy/middleware-retry": "^4.1.0", "@smithy/middleware-serde": "^4.0.3", "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.8", "@smithy/util-defaults-mode-node": "^4.0.8", "@smithy/util-endpoints": "^3.0.2", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-QOYC8q7luzHFXrP0xYAqBctoPkynjfV0r9dqntFu4/IWMTyC1vlo1UTxFAjIPyclYw92XJyEkVCVg9v/nQnsUA=="], "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.782.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/hash-node": "^4.0.2", "@smithy/invalid-dependency": "^4.0.2", "@smithy/middleware-content-length": "^4.0.2", "@smithy/middleware-endpoint": "^4.1.0", "@smithy/middleware-retry": "^4.1.0", "@smithy/middleware-serde": "^4.0.3", "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.8", "@smithy/util-defaults-mode-node": "^4.0.8", "@smithy/util-endpoints": "^3.0.2", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-5GlJBejo8wqMpSSEKb45WE82YxI2k73YuebjLH/eWDNQeE6VI5Bh9lA1YQ7xNkLLH8hIsb0pSfKVuwh0VEzVrg=="], @@ -6934,30 +7137,6 @@ "js-beautify/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "opencontrol/@modelcontextprotocol/sdk/express/accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], - - "opencontrol/@modelcontextprotocol/sdk/express/body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="], - - "opencontrol/@modelcontextprotocol/sdk/express/content-disposition": ["content-disposition@1.1.0", "", {}, "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g=="], - - "opencontrol/@modelcontextprotocol/sdk/express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], - - "opencontrol/@modelcontextprotocol/sdk/express/cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="], - - "opencontrol/@modelcontextprotocol/sdk/express/finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="], - - "opencontrol/@modelcontextprotocol/sdk/express/fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="], - - "opencontrol/@modelcontextprotocol/sdk/express/merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="], - - "opencontrol/@modelcontextprotocol/sdk/express/send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="], - - "opencontrol/@modelcontextprotocol/sdk/express/serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="], - - "opencontrol/@modelcontextprotocol/sdk/express/type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="], - - "ora/bl/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], - "pkg-dir/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], "pkg-up/find-up/locate-path/p-locate": ["p-locate@3.0.0", "", { "dependencies": { "p-limit": "^2.0.0" } }, "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ=="], @@ -6980,6 +7159,16 @@ "@aws-sdk/client-cognito-identity/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.2.3", "", {}, "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg=="], + "@aws-sdk/client-lambda/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/fast-xml-builder": ["fast-xml-builder@1.2.0", "", { "dependencies": { "path-expression-matcher": "^1.5.0", "xml-naming": "^0.1.0" } }, "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q=="], + + "@aws-sdk/client-lambda/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.2.3", "", {}, "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini/@aws-sdk/nested-clients/@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/signature-v4": "^5.4.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-0Phbz4t6HI3D3skxvG2uI+VWU034/nSIw1T8d+FPzzQG9EQTrw94o9mOKO2Gv3n3Oc8P7JD7RAUxkoneLWv5Eg=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/nested-clients/@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/signature-v4": "^5.4.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-0Phbz4t6HI3D3skxvG2uI+VWU034/nSIw1T8d+FPzzQG9EQTrw94o9mOKO2Gv3n3Oc8P7JD7RAUxkoneLWv5Eg=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity/@aws-sdk/nested-clients/@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.8", "@smithy/core": "^3.24.2", "@smithy/signature-v4": "^5.4.2", "@smithy/types": "^4.14.1", "tslib": "^2.6.2" } }, "sha512-0Phbz4t6HI3D3skxvG2uI+VWU034/nSIw1T8d+FPzzQG9EQTrw94o9mOKO2Gv3n3Oc8P7JD7RAUxkoneLWv5Eg=="], + "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini/@aws-sdk/nested-clients/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/client-sso/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], @@ -7054,8 +7243,6 @@ "js-beautify/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "opencontrol/@modelcontextprotocol/sdk/express/type-is/media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="], - "pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], "pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], @@ -7064,6 +7251,12 @@ "tw-to-css/tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini/@aws-sdk/nested-clients/@aws-sdk/signature-v4-multi-region/@smithy/signature-v4": ["@smithy/signature-v4@5.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-53+75QuPl6DL+ct6vVEB51FDO5oulXr20TPV46VvJZg76lIlXNWfxi8j+G2V/t0I2qxCBOa3vX/8bmjrpFVo9g=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/nested-clients/@aws-sdk/signature-v4-multi-region/@smithy/signature-v4": ["@smithy/signature-v4@5.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-53+75QuPl6DL+ct6vVEB51FDO5oulXr20TPV46VvJZg76lIlXNWfxi8j+G2V/t0I2qxCBOa3vX/8bmjrpFVo9g=="], + + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity/@aws-sdk/nested-clients/@aws-sdk/signature-v4-multi-region/@smithy/signature-v4": ["@smithy/signature-v4@5.4.3", "", { "dependencies": { "@smithy/core": "^3.24.3", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-53+75QuPl6DL+ct6vVEB51FDO5oulXr20TPV46VvJZg76lIlXNWfxi8j+G2V/t0I2qxCBOa3vX/8bmjrpFVo9g=="], + "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/token-providers/@aws-sdk/nested-clients/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], "@aws-sdk/credential-provider-cognito-identity/@aws-sdk/nested-clients/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.2.3", "", {}, "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg=="], diff --git a/infra/app.ts b/infra/app.ts index 2ede5a1f4a29..7b532bcb23f3 100644 --- a/infra/app.ts +++ b/infra/app.ts @@ -30,7 +30,7 @@ export const api = new sst.cloudflare.Worker("Api", { transform: { worker: (args) => { args.logpush = true - if ($app.stage === "vimtor") return + if ($app.stage === "vimtor" || $app.stage === "adam") return args.bindings = $resolve(args.bindings).apply((bindings) => [ ...bindings, { diff --git a/infra/console.ts b/infra/console.ts index 29e473de37a0..0a304a7be309 100644 --- a/infra/console.ts +++ b/infra/console.ts @@ -1,7 +1,9 @@ -import { domain } from "./stage" +import { deployAws, domain } from "./stage" import { EMAILOCTOPUS_API_KEY } from "./app" import { SECRET } from "./secret" +const lake = deployAws ? await import("./lake") : undefined + //////////////// // DATABASE //////////////// @@ -240,7 +242,7 @@ const SALESFORCE_INSTANCE_URL = new sst.Secret("SALESFORCE_INSTANCE_URL") const logProcessor = new sst.cloudflare.Worker("LogProcessor", { handler: "packages/console/function/src/log-processor.ts", - link: [new sst.Secret("HONEYCOMB_API_KEY")], + link: [SECRET.HoneycombApiKey, ...(lake?.lakeIngest ? [lake.lakeIngest] : [])], }) new sst.cloudflare.x.SolidStart("Console", { @@ -250,6 +252,8 @@ new sst.cloudflare.x.SolidStart("Console", { bucket, bucketNew, database, + SECRET.UpstashRedisRestUrl, + SECRET.UpstashRedisRestToken, AUTH_API_URL, STRIPE_WEBHOOK_SECRET, DISCORD_INCIDENT_WEBHOOK_URL, @@ -281,7 +285,7 @@ new sst.cloudflare.x.SolidStart("Console", { }, transform: { server: { - placement: { region: "aws:us-east-1" }, + placement: { region: "aws:us-east-2" }, transform: { worker: { tailConsumers: [{ service: logProcessor.nodes.worker.scriptName }], diff --git a/infra/lake.ts b/infra/lake.ts new file mode 100644 index 000000000000..c62bb155668d --- /dev/null +++ b/infra/lake.ts @@ -0,0 +1,322 @@ +import { domain } from "./stage" + +const current = aws.getCallerIdentityOutput({}) +const partition = aws.getPartitionOutput({}) +const region = aws.getRegionOutput({}) + +const tableBucketName = `opencode-${$app.stage}-lake` +const glueCatalogName = "s3tablescatalog" +const glueCatalogArn = $interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:catalog` +const glueS3TablesCatalogArn = $interpolate`${glueCatalogArn}/${glueCatalogName}` +const glueS3TablesChildCatalogArn = $interpolate`${glueS3TablesCatalogArn}/${tableBucketName}` +const glueS3TablesDatabaseWildcardArn = $interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:database/${glueCatalogName}/${tableBucketName}/*` +const glueS3TablesTableWildcardArn = $interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:table/${glueCatalogName}/${tableBucketName}/*/*` +const s3TablesBucketWildcardArn = $interpolate`arn:${partition.partition}:s3tables:${region.region}:${current.accountId}:bucket/*` + +export const tableBucket = new aws.s3tables.TableBucket("LakeTableBucket", { + name: tableBucketName, + forceDestroy: $app.stage !== "production", +}) + +const s3TablesCatalog = new aws.cloudcontrol.Resource( + "LakeS3TablesCatalog", + { + typeName: "AWS::Glue::Catalog", + desiredState: $jsonStringify({ + Name: glueCatalogName, + Description: "Federated catalog for S3 Tables", + FederatedCatalog: { + Identifier: s3TablesBucketWildcardArn, + ConnectionName: "aws:s3tables", + }, + CreateDatabaseDefaultPermissions: [ + { + Principal: { + DataLakePrincipalIdentifier: "IAM_ALLOWED_PRINCIPALS", + }, + Permissions: ["ALL"], + }, + ], + CreateTableDefaultPermissions: [ + { + Principal: { + DataLakePrincipalIdentifier: "IAM_ALLOWED_PRINCIPALS", + }, + Permissions: ["ALL"], + }, + ], + AllowFullTableExternalDataAccess: "True", + }), + }, + { dependsOn: [tableBucket] }, +) + +const athenaResultsBucket = new aws.s3.Bucket("LakeAthenaResults", { + bucket: `opencode-${$app.stage}-lake-athena-results`, + forceDestroy: $app.stage !== "production", +}) + +const firehoseErrorBucket = new aws.s3.Bucket("LakeFirehoseErrors", { + bucket: `opencode-${$app.stage}-lake-firehose-errors`, + forceDestroy: $app.stage !== "production", +}) + +const athenaWorkgroup = new aws.athena.Workgroup("LakeAthenaWorkgroup", { + name: `opencode-${$app.stage}-lake-workgroup`, + forceDestroy: $app.stage !== "production", + configuration: { + enforceWorkgroupConfiguration: true, + publishCloudwatchMetricsEnabled: true, + resultConfiguration: { + outputLocation: $interpolate`s3://${athenaResultsBucket.bucket}/`, + }, + }, +}) + +const firehoseRole = new aws.iam.Role("LakeFirehoseRole", { + assumeRolePolicy: aws.iam.getPolicyDocumentOutput({ + statements: [ + { + effect: "Allow", + actions: ["sts:AssumeRole"], + principals: [ + { + type: "Service", + identifiers: ["firehose.amazonaws.com"], + }, + ], + }, + ], + }).json, +}) + +const firehosePolicy = new aws.iam.RolePolicy("LakeFirehosePolicy", { + role: firehoseRole.id, + policy: aws.iam.getPolicyDocumentOutput({ + statements: [ + { + effect: "Allow", + actions: [ + "s3tables:ListTableBuckets", + "s3tables:GetTableBucket", + "s3tables:GetNamespace", + "s3tables:GetTable", + "s3tables:GetTableData", + "s3tables:GetTableMetadataLocation", + "s3tables:ListNamespaces", + "s3tables:ListTables", + "s3tables:PutTableData", + "s3tables:UpdateTableMetadataLocation", + ], + resources: ["*"], + }, + { + effect: "Allow", + actions: [ + "glue:GetCatalog", + "glue:GetCatalogs", + "glue:GetDatabase", + "glue:GetDatabases", + "glue:GetTable", + "glue:GetTables", + "glue:UpdateTable", + ], + resources: [ + glueCatalogArn, + glueS3TablesCatalogArn, + $interpolate`${glueS3TablesCatalogArn}/*`, + glueS3TablesDatabaseWildcardArn, + glueS3TablesTableWildcardArn, + $interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:database/*`, + $interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:table/*/*`, + $interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:table/${glueCatalogName}/*`, + ], + }, + { + effect: "Allow", + actions: [ + "s3:AbortMultipartUpload", + "s3:GetBucketLocation", + "s3:GetObject", + "s3:ListBucket", + "s3:ListBucketMultipartUploads", + "s3:PutObject", + ], + resources: [firehoseErrorBucket.arn, $interpolate`${firehoseErrorBucket.arn}/*`], + }, + { + effect: "Allow", + actions: ["lakeformation:GetDataAccess"], + resources: ["*"], + }, + ], + }).json, +}) + +const firehose = new aws.kinesis.FirehoseDeliveryStream( + "LakeFirehose", + { + name: `opencode-${$app.stage}-lake-ingest`, + destination: "iceberg", + icebergConfiguration: { + appendOnly: true, + bufferingInterval: 60, + bufferingSize: 1, + catalogArn: glueS3TablesChildCatalogArn, + processingConfiguration: { + enabled: true, + processors: [ + { + type: "MetadataExtraction", + parameters: [ + { parameterName: "JsonParsingEngine", parameterValue: "JQ-1.6" }, + { + parameterName: "MetadataExtractionQuery", + parameterValue: + '{destinationDatabaseName:._lake_database,destinationTableName:._lake_table,operation:(._lake_operation // "insert")}', + }, + ], + }, + ], + }, + roleArn: firehoseRole.arn, + s3BackupMode: "FailedDataOnly", + s3Configuration: { + roleArn: firehoseRole.arn, + bucketArn: firehoseErrorBucket.arn, + errorOutputPrefix: "errors/!{firehose:error-output-type}/", + }, + }, + }, + { dependsOn: [s3TablesCatalog, firehosePolicy] }, +) + +export const lakeVpc = new sst.aws.Vpc("LakeVpc") +export const lakeCluster = new sst.aws.Cluster("LakeCluster", { vpc: lakeVpc }) +export const lakeRegion = region.region +export const lakeCatalog = $interpolate`${glueCatalogName}/${tableBucket.name}` +export const lakeAthenaWorkgroup = athenaWorkgroup + +const ingestSecret = new random.RandomPassword("LakeIngestSecret", { length: 32 }) + +const ingestConfig = new sst.Linkable("LakeIngestConfig", { + properties: { + streamName: firehose.name, + secret: ingestSecret.result, + }, +}) + +const ingestService = new sst.aws.Service("LakeIngestService", { + cluster: lakeCluster, + architecture: "arm64", + cpu: "1 vCPU", + memory: "4 GB", + image: { + context: ".", + dockerfile: "packages/stats/server/Dockerfile", + }, + link: [ingestConfig], + permissions: [ + { + actions: ["firehose:PutRecord", "firehose:PutRecordBatch"], + resources: [firehose.arn], + }, + ], + scaling: { + min: $app.stage === "production" ? 2 : 1, + max: $app.stage === "production" ? 32 : 4, + cpuUtilization: 60, + memoryUtilization: 70, + }, + loadBalancer: { + domain: { + name: `lake.${domain}`, + dns: sst.cloudflare.dns(), + }, + rules: [ + { listen: "80/http", redirect: "443/https" }, + { listen: "443/https", forward: "3000/http" }, + ], + health: { + "3000/http": { + path: "/ready", + successCodes: "200-299", + }, + }, + }, + health: { + command: [ + "CMD-SHELL", + "bun --eval \"fetch('http://localhost:3000/health').then((r) => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))\"", + ], + interval: "30 seconds", + retries: 3, + startPeriod: "30 seconds", + timeout: "5 seconds", + }, + dev: { + command: "bun run start", + directory: "packages/stats/server", + url: "http://localhost:3000", + }, + wait: $app.stage === "production", +}) + +export const lakeIngest = new sst.Linkable("LakeIngest", { + properties: { + url: ingestService.url, + secret: ingestSecret.result, + }, +}) + +export const lakeQueryPermissions = [ + { + actions: ["athena:StartQueryExecution", "athena:GetQueryExecution", "athena:GetQueryResults"], + resources: [athenaWorkgroup.arn], + }, + { + actions: [ + "glue:GetCatalog", + "glue:GetCatalogs", + "glue:GetDatabase", + "glue:GetDatabases", + "glue:GetTable", + "glue:GetTables", + "glue:GetPartitions", + ], + resources: [ + glueCatalogArn, + glueS3TablesCatalogArn, + $interpolate`${glueS3TablesCatalogArn}/*`, + glueS3TablesDatabaseWildcardArn, + glueS3TablesTableWildcardArn, + $interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:database/*`, + $interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:table/*/*`, + $interpolate`arn:${partition.partition}:glue:${region.region}:${current.accountId}:table/${glueCatalogName}/*`, + ], + }, + { + actions: ["s3:GetBucketLocation", "s3:ListBucket"], + resources: [athenaResultsBucket.arn], + }, + { + actions: ["s3:GetObject", "s3:PutObject", "s3:AbortMultipartUpload", "s3:ListBucketMultipartUploads"], + resources: [$interpolate`${athenaResultsBucket.arn}/*`], + }, + { + actions: [ + "s3tables:GetTableBucket", + "s3tables:GetNamespace", + "s3tables:GetTable", + "s3tables:GetTableData", + "s3tables:GetTableMetadataLocation", + "s3tables:ListNamespaces", + "s3tables:ListTables", + ], + resources: ["*"], + }, + { + actions: ["lakeformation:GetDataAccess"], + resources: ["*"], + }, +] diff --git a/infra/monitoring.ts b/infra/monitoring.ts index 6e500367c1c5..b5521d61ce24 100644 --- a/infra/monitoring.ts +++ b/infra/monitoring.ts @@ -4,7 +4,7 @@ import { domain } from "./stage" const description = "Managed by SST (Don't edit in Honeycomb UI)" const alertsDisabled = $app.stage !== "production" -const webhookRecipient = new honeycomb.WebhookRecipient("DiscordAlerts", { +const webhookRecipient = new honeycombio.WebhookRecipient("DiscordAlerts", { name: $app.stage === "production" ? "Discord Alerts" : `Discord Alerts (${$app.stage})`, url: `https://${domain}/honeycomb/webhook`, secret: SECRET.HoneycombWebhookSecret.result, @@ -67,7 +67,7 @@ IF( )`, }) - return honeycomb.getQuerySpecificationOutput({ + return honeycombio.getQuerySpecificationOutput({ breakdowns: ["model"], calculatedFields: [failedHttpStatus], calculations: [ @@ -99,7 +99,7 @@ const providerHttpErrorsQuery = () => { expression: `IF(GT($llm.error.code, "400"), 1, 0)`, }) - return honeycomb.getQuerySpecificationOutput({ + return honeycombio.getQuerySpecificationOutput({ breakdowns: ["provider"], calculatedFields: [successHttpStatus, failedProviderHttpStatus], calculations: [ @@ -140,7 +140,7 @@ const modelLowTpsQuery = (product: "go" | "zen") => { { column: "tps.output", op: "exists" }, ] - return honeycomb.getQuerySpecificationOutput({ + return honeycombio.getQuerySpecificationOutput({ breakdowns: ["model"], calculations: [ { op: "COUNT", name: "TOTAL", filterCombination: "AND", filters }, @@ -157,7 +157,7 @@ const modelLowTpsQuery = (product: "go" | "zen") => { }).json } -new honeycomb.Trigger("IncreasedModelHttpErrorsGo", { +new honeycombio.Trigger("IncreasedModelHttpErrorsGo", { name: "Increased Model HTTP Errors [Go]", description, disabled: alertsDisabled, @@ -177,7 +177,7 @@ new honeycomb.Trigger("IncreasedModelHttpErrorsGo", { ], }) -new honeycomb.Trigger("IncreasedModelHttpErrorsZen", { +new honeycombio.Trigger("IncreasedModelHttpErrorsZen", { name: "Increased Model HTTP Errors [Zen]", description, disabled: alertsDisabled, @@ -197,7 +197,7 @@ new honeycomb.Trigger("IncreasedModelHttpErrorsZen", { ], }) -new honeycomb.Trigger("LowModelTpsGo", { +new honeycombio.Trigger("LowModelTpsGo", { name: "Low Model TPS [Go]", description, disabled: alertsDisabled, @@ -217,7 +217,7 @@ new honeycomb.Trigger("LowModelTpsGo", { ], }) -new honeycomb.Trigger("LowModelTpsZen", { +new honeycombio.Trigger("LowModelTpsZen", { name: "Low Model TPS [Zen]", description, disabled: alertsDisabled, @@ -237,7 +237,7 @@ new honeycomb.Trigger("LowModelTpsZen", { ], }) -new honeycomb.Trigger("IncreasedProviderHttpErrors", { +new honeycombio.Trigger("IncreasedProviderHttpErrors", { name: "Increased Provider HTTP Errors", description, disabled: alertsDisabled, @@ -257,11 +257,11 @@ new honeycomb.Trigger("IncreasedProviderHttpErrors", { ], }) -new honeycomb.Trigger("IncreasedFreeTierRequests", { +new honeycombio.Trigger("IncreasedFreeTierRequests", { name: "Increased Free Tier Requests", description, disabled: alertsDisabled, - queryJson: honeycomb.getQuerySpecificationOutput({ + queryJson: honeycombio.getQuerySpecificationOutput({ calculations: [{ op: "COUNT" }], filters: [ { column: "event_type", op: "=", value: "completions" }, diff --git a/infra/secret.ts b/infra/secret.ts index d4e8b148fc3a..65ada2f1f64d 100644 --- a/infra/secret.ts +++ b/infra/secret.ts @@ -7,5 +7,8 @@ sst.Linkable.wrap(random.RandomPassword, (resource) => ({ export const SECRET = { R2AccessKey: new sst.Secret("R2AccessKey", "unknown"), R2SecretKey: new sst.Secret("R2SecretKey", "unknown"), + HoneycombApiKey: new sst.Secret("HONEYCOMB_API_KEY"), HoneycombWebhookSecret: new random.RandomPassword("HoneycombWebhookSecret", { length: 24 }), + UpstashRedisRestUrl: new sst.Secret("UpstashRedisRestUrl"), + UpstashRedisRestToken: new sst.Secret("UpstashRedisRestToken"), } diff --git a/infra/stage.ts b/infra/stage.ts index f9a6fd75529c..8d80eefed880 100644 --- a/infra/stage.ts +++ b/infra/stage.ts @@ -5,6 +5,8 @@ export const domain = (() => { })() export const zoneID = "430ba34c138cfb5360826c4909f99be8" +export const awsStage = $app.stage === "production" ? "production" : "dev" +export const deployAws = $app.stage === awsStage new cloudflare.RegionalHostname("RegionalHostname", { hostname: domain, diff --git a/infra/stats.ts b/infra/stats.ts new file mode 100644 index 000000000000..28d50fe0e340 --- /dev/null +++ b/infra/stats.ts @@ -0,0 +1,207 @@ +import { lakeAthenaWorkgroup, lakeCatalog, lakeCluster, lakeQueryPermissions, lakeRegion, tableBucket } from "./lake" + +const domain = (() => { + if ($app.stage === "production") return "stats.opencode.ai" + if ($app.stage === "dev") return "stats.dev.opencode.ai" + return `stats.${$app.stage}.dev.opencode.ai` +})() + +//////////////// +// LAKE +//////////////// + +const inferenceNamespace = new aws.s3tables.Namespace("LakeInferenceNamespace", { + namespace: "inference", + tableBucketArn: tableBucket.arn, +}) + +const inferenceEventTable = new aws.s3tables.Table( + "LakeInferenceEventTable", + { + name: "event", + namespace: inferenceNamespace.namespace, + tableBucketArn: inferenceNamespace.tableBucketArn, + format: "ICEBERG", + metadata: { + iceberg: { + schema: { + fields: [ + { name: "event_timestamp", type: "string", required: false }, + { name: "event_date", type: "string", required: false }, + { name: "event_type", type: "string", required: false }, + { name: "dataset", type: "string", required: false }, + { name: "cf_continent", type: "string", required: false }, + { name: "cf_country", type: "string", required: false }, + { name: "cf_city", type: "string", required: false }, + { name: "cf_region", type: "string", required: false }, + { name: "cf_latitude", type: "double", required: false }, + { name: "cf_longitude", type: "double", required: false }, + { name: "cf_timezone", type: "string", required: false }, + { name: "duration", type: "double", required: false }, + { name: "request_length", type: "long", required: false }, + { name: "status", type: "int", required: false }, + { name: "ip", type: "string", required: false }, + { name: "is_stream", type: "boolean", required: false }, + { name: "session", type: "string", required: false }, + { name: "request", type: "string", required: false }, + { name: "client", type: "string", required: false }, + { name: "user_agent", type: "string", required: false }, + { name: "model_variant", type: "string", required: false }, + { name: "source", type: "string", required: false }, + { name: "provider", type: "string", required: false }, + { name: "provider_model", type: "string", required: false }, + { name: "model", type: "string", required: false }, + { name: "llm_error_code", type: "int", required: false }, + { name: "llm_error_message", type: "string", required: false }, + { name: "error_response", type: "string", required: false }, + { name: "error_type", type: "string", required: false }, + { name: "error_message", type: "string", required: false }, + { name: "error_cause", type: "string", required: false }, + { name: "error_cause2", type: "string", required: false }, + { name: "api_key", type: "string", required: false }, + { name: "workspace", type: "string", required: false }, + { name: "is_subscription", type: "boolean", required: false }, + { name: "subscription", type: "string", required: false }, + { name: "response_length", type: "long", required: false }, + { name: "time_to_first_byte", type: "long", required: false }, + { name: "timestamp_first_byte", type: "long", required: false }, + { name: "timestamp_last_byte", type: "long", required: false }, + { name: "tokens_input", type: "long", required: false }, + { name: "tokens_output", type: "long", required: false }, + { name: "tokens_reasoning", type: "long", required: false }, + { name: "tokens_cache_read", type: "long", required: false }, + { name: "tokens_cache_write_5m", type: "long", required: false }, + { name: "tokens_cache_write_1h", type: "long", required: false }, + { name: "cost_input_microcents", type: "long", required: false }, + { name: "cost_output_microcents", type: "long", required: false }, + { name: "cost_cache_read_microcents", type: "long", required: false }, + { name: "cost_cache_write_microcents", type: "long", required: false }, + { name: "cost_total_microcents", type: "long", required: false }, + { name: "cost_input", type: "long", required: false }, + { name: "cost_output", type: "long", required: false }, + { name: "cost_cache_read", type: "long", required: false }, + { name: "cost_cache_write_5m", type: "long", required: false }, + { name: "cost_cache_write_1h", type: "long", required: false }, + { name: "cost_total", type: "long", required: false }, + ], + }, + }, + }, + }, + { deleteBeforeReplace: $app.stage !== "production" }, +) + +export const inferenceEvent = new sst.Linkable("InferenceEvent", { + properties: { + region: lakeRegion, + catalog: lakeCatalog, + database: inferenceNamespace.namespace, + table: inferenceEventTable.name, + tableBucket: tableBucket.name, + workgroup: lakeAthenaWorkgroup.name, + }, +}) + +//////////////// +// DATABASE +//////////////// + +const cluster = planetscale.getDatabaseOutput({ + name: "opencode-stats", + organization: "anomalyco", +}) + +const branch = + $app.stage === "production" + ? planetscale.getBranchOutput({ + name: "production", + organization: cluster.organization, + database: cluster.name, + }) + : new planetscale.Branch("StatsDatabaseBranch", { + database: cluster.name, + organization: cluster.organization, + name: $app.stage, + parentBranch: "production", + }) + +const password = new planetscale.Password("StatsDatabasePassword", { + name: $app.stage, + database: cluster.name, + organization: cluster.organization, + branch: branch.name, +}) + +const databaseUrl = $interpolate`mysql://${password.username.apply(encodeURIComponent)}:${password.plaintext.apply( + encodeURIComponent, +)}@${password.accessHostUrl}/${cluster.name}` + +export const database = new sst.Linkable("StatsDatabase", { + properties: { + host: password.accessHostUrl, + database: cluster.name, + username: password.username, + password: password.plaintext, + port: 3306, + url: databaseUrl, + }, +}) + +new sst.x.DevCommand("StatsStudio", { + link: [database], + environment: { + DATABASE_URL: databaseUrl, + }, + dev: { + command: "bun db:studio", + directory: "packages/stats/core", + autostart: false, + }, +}) + +//////////////// +// APP +//////////////// + +// export const app = new sst.cloudflare.x.SolidStart("Stats", { +// path: "packages/stats/app", +// buildCommand: "bun run build", +// domain, +// link: [database], +// environment: { +// PUBLIC_URL: `https://${domain}`, +// }, +// }) + +//////////////// +// SERVICES +//////////////// + +const statsSyncConfig = new sst.Linkable("StatsSyncConfig", { + properties: { + dataset: "zen", + }, +}) + +export const statSync = new sst.aws.Service("StatsSyncService", { + cluster: lakeCluster, + architecture: "arm64", + cpu: "0.25 vCPU", + memory: "0.5 GB", + image: { + context: ".", + dockerfile: "packages/stats/server/Dockerfile", + }, + command: ["bun", "src/stat-sync.ts"], + link: [database, inferenceEvent, statsSyncConfig], + permissions: lakeQueryPermissions, + scaling: { + min: 1, + max: 1, + }, + dev: { + command: "bun src/stat-sync.ts", + directory: "packages/stats/server", + autostart: false, + }, +}) diff --git a/nix/desktop.nix b/nix/desktop.nix index c7ae65ada77a..d0d7fa7eca1f 100644 --- a/nix/desktop.nix +++ b/nix/desktop.nix @@ -3,6 +3,7 @@ stdenv, bun, nodejs, + darwin, electron_41, makeWrapper, writableTmpDirAsHomeHook, @@ -14,7 +15,12 @@ let in stdenv.mkDerivation (finalAttrs: { pname = "opencode-desktop"; - inherit (opencode) version src node_modules; + inherit (opencode) + version + src + node_modules + patches + ; nativeBuildInputs = [ bun @@ -23,6 +29,9 @@ stdenv.mkDerivation (finalAttrs: { writableTmpDirAsHomeHook ] ++ lib.optionals stdenv.hostPlatform.isLinux [ autoPatchelfHook + ] ++ lib.optionals stdenv.hostPlatform.isDarwin [ + # Ad-hoc sign the .app: --config.mac.identity=null below skips signing. + darwin.autoSignDarwinBinariesHook ]; buildInputs = lib.optionals stdenv.hostPlatform.isLinux [ diff --git a/nix/hashes.json b/nix/hashes.json index fc1532ddeb62..8d84bfe1e9dc 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-FI1mX42vJuYdUDdWevlfHz+OcYkDn/I/HUbHE/jdQvs=", - "aarch64-linux": "sha256-3CQzzKnh/4Zf5vyn56yR5P3ULsW7K7Fr8/RQpekEJDk=", - "aarch64-darwin": "sha256-XPDVHMxlPpXlf43BRqNnwF809unk6iE8tvd0o92d0/w=", - "x86_64-darwin": "sha256-dFXTi13RSgL62lMsep1EoE/KSEPF7Oh31PVdxW1tkzg=" + "x86_64-linux": "sha256-70om2TEJYJJOcf9lqex+Sxs27c1SVVgN7FNkLbTXBR0=", + "aarch64-linux": "sha256-/xTsjAFl6TmydJFXETctBoRePIFAkMyxv0HLWHFymJg=", + "aarch64-darwin": "sha256-/xbFzrnScm1x4xuz2rEJyyjockDMIIyqJtxm3Axghbg=", + "x86_64-darwin": "sha256-ZbJDPhmcvBlY80CPmzygw4S8mjdR+d/UyL+3R3nhZtM=" } } diff --git a/package.json b/package.json index c4bd48684062..5fecf69bab61 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "dev:desktop": "bun --cwd packages/desktop dev", "dev:web": "bun --cwd packages/app dev", "dev:console": "ulimit -n 10240 2>/dev/null; bun run --cwd packages/console/app dev", + "dev:stats": "bun sst shell --stage=production -- bun run --cwd packages/stats/app dev", "dev:storybook": "bun --cwd packages/storybook storybook", "lint": "oxlint", "typecheck": "bun turbo typecheck", @@ -17,27 +18,29 @@ "postinstall": "bun run --cwd packages/opencode fix-node-pty", "prepare": "husky", "random": "echo 'Random script'", - "hello": "echo 'Hello World!'", + "sso": "aws sso login --sso-session=opencode --no-browser", "test": "echo 'do not run tests from root' && exit 1" }, "workspaces": { "packages": [ "packages/*", "packages/console/*", + "packages/stats/*", "packages/sdk/js", "packages/slack" ], "catalog": { - "@effect/opentelemetry": "4.0.0-beta.65", - "@effect/platform-node": "4.0.0-beta.65", + "@effect/opentelemetry": "4.0.0-beta.66", + "@effect/platform-node": "4.0.0-beta.66", + "@effect/sql-sqlite-bun": "4.0.0-beta.66", "@npmcli/arborist": "9.4.0", "@types/bun": "1.3.13", "@types/cross-spawn": "6.0.6", "@octokit/rest": "22.0.0", "@hono/zod-validator": "0.4.2", - "@opentui/core": "0.2.14", - "@opentui/keymap": "0.2.14", - "@opentui/solid": "0.2.14", + "@opentui/core": "0.2.16", + "@opentui/keymap": "0.2.16", + "@opentui/solid": "0.2.16", "ulid": "3.0.1", "@kobalte/core": "0.13.11", "@types/luxon": "3.7.1", @@ -53,9 +56,9 @@ "@tailwindcss/vite": "4.1.11", "diff": "8.0.2", "dompurify": "3.3.1", - "drizzle-kit": "1.0.0-beta.19-d95b7a4", - "drizzle-orm": "1.0.0-beta.19-d95b7a4", - "effect": "4.0.0-beta.65", + "drizzle-kit": "1.0.0-rc.2", + "drizzle-orm": "1.0.0-rc.2", + "effect": "4.0.0-beta.66", "ai": "6.0.168", "cross-spawn": "7.0.6", "hono": "4.10.7", @@ -71,6 +74,7 @@ "@typescript/native-preview": "7.0.0-dev.20251207.1", "zod": "4.1.8", "remeda": "2.26.0", + "sst": "4.13.1", "shiki": "3.20.0", "solid-list": "0.3.0", "tailwindcss": "4.1.11", @@ -97,7 +101,7 @@ "oxlint-tsgolint": "0.21.0", "prettier": "3.6.2", "semver": "^7.6.0", - "sst": "3.18.10", + "sst": "catalog:", "turbo": "2.8.13" }, "dependencies": { @@ -138,6 +142,9 @@ "@npmcli/agent@4.0.0": "patches/@npmcli%2Fagent@4.0.0.patch", "@silvia-odwyer/photon-node@0.3.4": "patches/@silvia-odwyer%2Fphoton-node@0.3.4.patch", "@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch", - "solid-js@1.9.10": "patches/solid-js@1.9.10.patch" + "solid-js@1.9.10": "patches/solid-js@1.9.10.patch", + "virtua@0.49.1": "patches/virtua@0.49.1.patch", + "@ai-sdk/xai@3.0.82": "patches/@ai-sdk%2Fxai@3.0.82.patch", + "gcp-metadata@8.1.2": "patches/gcp-metadata@8.1.2.patch" } } diff --git a/packages/app/e2e/regression/session-timeline-collapse-state.spec.ts b/packages/app/e2e/regression/session-timeline-collapse-state.spec.ts new file mode 100644 index 000000000000..88b140a61dba --- /dev/null +++ b/packages/app/e2e/regression/session-timeline-collapse-state.spec.ts @@ -0,0 +1,352 @@ +import { expect, test, type Locator, type Page } from "@playwright/test" +import { mockOpenCodeServer } from "../utils/mock-server" + +const directory = "C:/OpenCode/TimelineStateRegression" +const projectID = "proj_timeline_state_regression" +const sessionID = "ses_timeline_state_regression" +const userMessageID = "msg_user_regression" +const assistantMessageID = "msg_assistant_regression" +const editPartID = "prt_0001_edit" +const textPartID = "prt_9999_text" +const title = "Timeline collapse state regression" +const model = { providerID: "opencode", modelID: "claude-opus-4-6", variant: "max" } + +type EventPayload = { + directory: string + payload: Record +} + +declare global { + interface Window { + __timelineDiffProbe: { + reset: () => void + shadowRoots: () => number + } + } +} + +const userMessage = { + info: { + id: userMessageID, + sessionID, + role: "user", + time: { created: 1700000000000 }, + summary: { diffs: [] }, + agent: "build", + model, + }, + parts: [ + { + id: "prt_user_text", + sessionID, + messageID: userMessageID, + type: "text", + text: "Please edit the file.", + }, + ], +} + +const editPart = { + id: editPartID, + sessionID, + messageID: assistantMessageID, + type: "tool", + callID: "call_edit_regression", + tool: "edit", + state: { + status: "completed", + input: { filePath: "src/regression.ts" }, + output: "Edited src/regression.ts", + title: "src/regression.ts", + metadata: { + filediff: { + file: "src/regression.ts", + additions: 1, + deletions: 1, + before: "export const value = 'before'\n", + after: "export const value = 'after'\n", + }, + diff: "diff --git a/src/regression.ts b/src/regression.ts\n-export const value = 'before'\n+export const value = 'after'\n", + }, + time: { start: 1700000001000, end: 1700000002000 }, + }, +} + +const streamedTextPart = { + id: textPartID, + sessionID, + messageID: assistantMessageID, + type: "text", + text: "Streaming added a later assistant text part.", +} + +const assistantMessage = { + info: { + id: assistantMessageID, + sessionID, + role: "assistant", + time: { created: 1700000001000 }, + parentID: userMessageID, + modelID: model.modelID, + providerID: model.providerID, + mode: "build", + agent: "build", + path: { cwd: directory, root: directory }, + cost: 0.01, + tokens: { input: 100, output: 200, reasoning: 0, cache: { read: 0, write: 0 } }, + variant: "max", + }, + parts: [editPart], +} + +test.describe("regression: session timeline local row state", () => { + test("keeps a manually collapsed tool collapsed when later assistant content streams", async ({ page }) => { + const events: EventPayload[] = [] + await mockServer(page, events) + await configurePage(page) + + await page.goto(`/${base64Encode(directory)}/session/${sessionID}`) + await expect(page.getByRole("heading", { name: title })).toBeVisible() + + const wrapper = page.locator(`[data-timeline-part-id="${editPartID}"]`).first() + await expect(wrapper).toBeVisible() + await expectExpanded(wrapper, true) + + await wrapper.evaluate((element) => { + ;(element as HTMLElement).dataset.regressionMarker = "before-stream" + }) + await wrapper.locator('[data-slot="collapsible-trigger"]').first().click() + await expectExpanded(wrapper, false) + + events.push({ + directory, + payload: { + type: "message.part.updated", + properties: { part: streamedTextPart }, + }, + }) + + await expect(page.locator(`[data-timeline-part-id="${textPartID}"]`).first()).toBeVisible({ timeout: 10_000 }) + + expect(await readToolState(page)).toEqual({ + expanded: false, + row: "AssistantPart", + streamedTextVisible: true, + }) + }) + + test("does not remount an edit diff when sibling parts or diff counts update", async ({ page }) => { + const events: EventPayload[] = [] + await installDiffProbe(page) + await mockServer(page, events) + await configurePage(page) + + await page.goto(`/${base64Encode(directory)}/session/${sessionID}`) + await expect(page.getByRole("heading", { name: title })).toBeVisible() + + const wrapper = page.locator(`[data-timeline-part-id="${editPartID}"]`).first() + await expect(wrapper).toBeVisible() + await expect(wrapper.locator('[data-component="file"][data-mode="diff"]').first()).toBeVisible() + await markDiffProbe(page) + + events.push({ + directory, + payload: { + type: "message.part.updated", + properties: { part: streamedTextPart }, + }, + }) + + await expect(page.locator(`[data-timeline-part-id="${textPartID}"]`).first()).toBeVisible({ timeout: 10_000 }) + expect(await readDiffProbe(page)).toEqual({ fileMarker: "before", shadowRoots: 0, toolMarker: "before" }) + + await markDiffProbe(page) + events.push({ + directory, + payload: { + type: "message.part.updated", + properties: { part: editPartWithAdditions(2) }, + }, + }) + + await expect(wrapper.locator('[data-slot="diff-changes-additions"]').filter({ hasText: "+2" }).first()).toBeVisible( + { timeout: 10_000 }, + ) + expect(await readDiffProbe(page)).toEqual({ fileMarker: "before", shadowRoots: 0, toolMarker: "before" }) + }) +}) + +async function configurePage(page: Page) { + await page.addInitScript(() => { + localStorage.setItem( + "settings.v3", + JSON.stringify({ + general: { + editToolPartsExpanded: true, + shellToolPartsExpanded: true, + showReasoningSummaries: true, + showSessionProgressBar: true, + }, + }), + ) + }) +} + +async function expectExpanded(locator: Locator, expected: boolean) { + await expect.poll(() => locator.evaluate(readExpanded)).toBe(expected) +} + +async function readToolState(page: Page) { + return page + .locator(`[data-timeline-part-id="${editPartID}"]`) + .first() + .evaluate( + (element, textPartID) => ({ + expanded: (() => { + const trigger = element.querySelector('[data-slot="collapsible-trigger"]') + const aria = trigger?.getAttribute("aria-expanded") + if (aria === "true") return true + if (aria === "false") return false + + const root = element.querySelector('[data-component="collapsible"]') + if (root?.hasAttribute("data-expanded")) return true + if (root?.hasAttribute("data-closed")) return false + + const content = element.querySelector('[data-slot="collapsible-content"]') + return !!content && content.getBoundingClientRect().height > 0 + })(), + row: element.closest("[data-timeline-row]")?.getAttribute("data-timeline-row"), + streamedTextVisible: !!document.querySelector(`[data-timeline-part-id="${textPartID}"]`), + }), + textPartID, + ) +} + +async function installDiffProbe(page: Page) { + await page.addInitScript(() => { + let shadowRootCount = 0 + const attachShadow = Element.prototype.attachShadow + Element.prototype.attachShadow = function (init) { + shadowRootCount += 1 + return attachShadow.call(this, init) + } + window.__timelineDiffProbe = { + reset: () => { + shadowRootCount = 0 + }, + shadowRoots: () => shadowRootCount, + } + }) +} + +async function markDiffProbe(page: Page) { + await page + .locator(`[data-timeline-part-id="${editPartID}"]`) + .first() + .evaluate((element) => { + const tool = element as HTMLElement + const file = tool.querySelector('[data-component="file"][data-mode="diff"]') + if (!file) throw new Error("missing edit diff file") + + tool.dataset.timelineProbe = "before" + file.dataset.timelineProbe = "before" + window.__timelineDiffProbe.reset() + }) +} + +async function readDiffProbe(page: Page) { + return page + .locator(`[data-timeline-part-id="${editPartID}"]`) + .first() + .evaluate((element) => { + const tool = element as HTMLElement + const file = tool.querySelector('[data-component="file"][data-mode="diff"]') + return { + fileMarker: file?.dataset.timelineProbe, + shadowRoots: window.__timelineDiffProbe.shadowRoots(), + toolMarker: tool.dataset.timelineProbe, + } + }) +} + +function editPartWithAdditions(additions: number) { + return { + ...editPart, + state: { + ...editPart.state, + metadata: { + ...editPart.state.metadata, + filediff: { + ...editPart.state.metadata.filediff, + additions, + }, + }, + }, + } +} + +function readExpanded(element: Element) { + const trigger = element.querySelector('[data-slot="collapsible-trigger"]') + const aria = trigger?.getAttribute("aria-expanded") + if (aria === "true") return true + if (aria === "false") return false + + const root = element.querySelector('[data-component="collapsible"]') + if (root?.hasAttribute("data-expanded")) return true + if (root?.hasAttribute("data-closed")) return false + + const content = element.querySelector('[data-slot="collapsible-content"]') + return !!content && content.getBoundingClientRect().height > 0 +} + +async function mockServer(page: Page, events: EventPayload[]) { + await mockOpenCodeServer(page, { + directory, + project: project(), + provider: provider(), + sessions: [session()], + pageMessages: () => ({ items: [userMessage, assistantMessage] }), + events: () => events.splice(0), + }) +} + +function project() { + return { + id: projectID, + worktree: directory, + vcs: "git", + name: "timeline-state-regression", + time: { created: 1700000000000, updated: 1700000000000 }, + sandboxes: [], + } +} + +function session() { + return { + id: sessionID, + slug: "timeline-state-regression", + projectID, + directory, + title, + version: "dev", + time: { created: 1700000000000, updated: 1700000000000 }, + } +} + +function provider() { + return { + all: [ + { + id: "opencode", + name: "OpenCode", + models: { "claude-opus-4-6": { id: "claude-opus-4-6", name: "Claude Opus 4.6", limit: { context: 200_000 } } }, + }, + ], + connected: ["opencode"], + default: { providerID: "opencode", modelID: "claude-opus-4-6" }, + } +} + +function base64Encode(value: string) { + return Buffer.from(value, "utf8").toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "") +} diff --git a/packages/app/e2e/regression/session-timeline-context-resize.spec.ts b/packages/app/e2e/regression/session-timeline-context-resize.spec.ts new file mode 100644 index 000000000000..dc72e24f0df9 --- /dev/null +++ b/packages/app/e2e/regression/session-timeline-context-resize.spec.ts @@ -0,0 +1,267 @@ +import { expect, test, type Page } from "@playwright/test" +import { mockOpenCodeServer } from "../utils/mock-server" + +const directory = "C:/OpenCode/ContextResizeRegression" +const projectID = "proj_context_resize_regression" +const sessionID = "ses_context_resize_regression" +const title = "Context resize regression" +const model = { providerID: "opencode", modelID: "claude-opus-4-6", variant: "max" } +const contextIDs = ["prt_0100_read", "prt_0101_glob", "prt_0102_grep", "prt_0103_list"] +const followingTextID = "prt_0104_text" + +type Message = { + info: Record & { id: string; role: "user" | "assistant" } + parts: Record[] +} + +const messages = [...Array.from({ length: 8 }, (_, index) => turn(index, false)).flat(), ...turn(10, true)] + +test.describe("regression: session timeline context group resize", () => { + test("remeasures a recent explored context group before the next paint", async ({ page }) => { + await page.setViewportSize({ width: 1400, height: 900 }) + await mockServer(page) + await configurePage(page) + + await page.goto(`/${base64Encode(directory)}/session/${sessionID}`) + await expect(page.getByRole("heading", { name: title })).toBeVisible() + await expect(page.locator(`[data-timeline-part-ids="${contextIDs.join(",")}"]`).first()).toBeVisible() + await expect(page.locator(`[data-timeline-part-id="${followingTextID}"]`).first()).toBeVisible() + await settle(page) + + const samples = await sampleExpansion(page) + const visibleOverlap = samples.filter((sample) => sample.frame >= 1 && sample.overlap > 0.5) + + console.log("context resize samples", JSON.stringify(samples, null, 2)) + + expect(samples[0]?.overlap).toBe(0) + expect(visibleOverlap).toEqual([]) + expect(samples.at(-1)?.expanded).toBe("true") + }) +}) + +async function configurePage(page: Page) { + await page.addInitScript(() => { + localStorage.setItem( + "settings.v3", + JSON.stringify({ + general: { + editToolPartsExpanded: true, + shellToolPartsExpanded: true, + showReasoningSummaries: true, + showSessionProgressBar: true, + }, + }), + ) + }) +} + +async function sampleExpansion(page: Page) { + return page.evaluate( + ({ contextIDs, followingTextID }) => + new Promise< + { + frame: number + label: string + scrollTop: number + scrollHeight: number + contextBottom: number + textTop: number + overlap: number + gap: number + expanded: string | null + }[] + >((resolve) => { + const context = document.querySelector(`[data-timeline-part-ids="${contextIDs.join(",")}"]`) + const text = document.querySelector(`[data-timeline-part-id="${followingTextID}"]`) + const scroller = context?.closest(".scroll-view__viewport") + const trigger = context?.querySelector('[data-slot="collapsible-trigger"]') + const contextRow = context?.closest('[data-timeline-row="AssistantPart"]') + const textRow = text?.closest('[data-timeline-row="AssistantPart"]') + if (!context || !text || !scroller || !trigger || !contextRow || !textRow) + throw new Error("missing regression nodes") + + scroller.scrollTop = scroller.scrollHeight + const samples: { + frame: number + label: string + scrollTop: number + scrollHeight: number + contextBottom: number + textTop: number + overlap: number + gap: number + expanded: string | null + }[] = [] + const capture = (frame: number, label: string) => { + const contextRect = contextRow.getBoundingClientRect() + const textRect = textRow.getBoundingClientRect() + samples.push({ + frame, + label, + scrollTop: Math.round(scroller.scrollTop * 10) / 10, + scrollHeight: Math.round(scroller.scrollHeight * 10) / 10, + contextBottom: Math.round(contextRect.bottom * 10) / 10, + textTop: Math.round(textRect.top * 10) / 10, + overlap: Math.max(0, Math.round((contextRect.bottom - textRect.top) * 10) / 10), + gap: Math.max(0, Math.round((textRect.top - contextRect.bottom) * 10) / 10), + expanded: trigger.getAttribute("aria-expanded"), + }) + } + + capture(-1, "before") + trigger.click() + capture(0, "sync-after-click") + + let frame = 1 + const tick = () => { + capture(frame, "raf") + frame += 1 + if (frame > 8) { + resolve(samples) + return + } + requestAnimationFrame(tick) + } + requestAnimationFrame(tick) + }), + { contextIDs, followingTextID }, + ) +} + +function turn(index: number, target: boolean): Message[] { + const userID = id("msg_user", index) + const assistantID = id("msg_assistant", index) + return [ + { + info: { + id: userID, + sessionID, + role: "user", + time: { created: 1700000000000 + index * 10_000 }, + summary: { diffs: [] }, + agent: "build", + model, + }, + parts: [{ id: id("prt_user", index), sessionID, messageID: userID, type: "text", text: `User message ${index}` }], + }, + { + info: { + id: assistantID, + sessionID, + role: "assistant", + time: { created: 1700000000000 + index * 10_000 + 1_000, completed: 1700000000000 + index * 10_000 + 2_000 }, + parentID: userID, + modelID: model.modelID, + providerID: model.providerID, + mode: "build", + agent: "build", + path: { cwd: directory, root: directory }, + cost: 0.01, + tokens: { input: 100, output: 200, reasoning: 0, cache: { read: 0, write: 0 } }, + variant: "max", + finish: "stop", + }, + parts: target + ? [ + contextTool(contextIDs[0]!, assistantID, "read", { filePath: "src/recent-a.ts", offset: 0, limit: 120 }), + contextTool(contextIDs[1]!, assistantID, "glob", { path: directory, pattern: "**/*.ts" }), + contextTool(contextIDs[2]!, assistantID, "grep", { path: directory, pattern: "Explored", include: "*.ts" }), + contextTool(contextIDs[3]!, assistantID, "list", { path: "src" }), + { + id: followingTextID, + sessionID, + messageID: assistantID, + type: "text", + text: "This assistant text is immediately after the explored context group.", + }, + ] + : [ + { + id: id("prt_text", index), + sessionID, + messageID: assistantID, + type: "text", + text: `Assistant filler ${index}. ${"filler ".repeat(60)}`, + }, + ], + }, + ] +} + +function contextTool(partID: string, messageID: string, tool: string, input: Record) { + return { + id: partID, + sessionID, + messageID, + type: "tool", + callID: `call_${partID}`, + tool, + state: { + status: "completed", + input, + output: `Completed ${tool}.\n${"detail line\n".repeat(8)}`, + title: input.filePath || input.path || input.pattern || "completed", + metadata: {}, + time: { start: 1700000000000, end: 1700000000100 }, + }, + } +} + +async function mockServer(page: Page) { + await mockOpenCodeServer(page, { + directory, + project: project(), + provider: provider(), + sessions: [session()], + pageMessages: () => ({ items: messages }), + }) +} + +async function settle(page: Page) { + await page.evaluate(() => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)))) +} + +function id(prefix: string, index: number) { + return `${prefix}_${String(index).padStart(4, "0")}` +} + +function project() { + return { + id: projectID, + worktree: directory, + vcs: "git", + name: "context-resize-regression", + time: { created: 1700000000000, updated: 1700000000000 }, + sandboxes: [], + } +} + +function session() { + return { + id: sessionID, + slug: "context-resize-regression", + projectID, + directory, + title, + version: "dev", + time: { created: 1700000000000, updated: 1700000000000 }, + } +} + +function provider() { + return { + all: [ + { + id: "opencode", + name: "OpenCode", + models: { "claude-opus-4-6": { id: "claude-opus-4-6", name: "Claude Opus 4.6", limit: { context: 200_000 } } }, + }, + ], + connected: ["opencode"], + default: { providerID: "opencode", modelID: "claude-opus-4-6" }, + } +} + +function base64Encode(value: string) { + return Buffer.from(value, "utf8").toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "") +} diff --git a/packages/app/e2e/smoke/session-timeline.spec.ts b/packages/app/e2e/smoke/session-timeline.spec.ts index 3dda017dde4d..af413ffffbba 100644 --- a/packages/app/e2e/smoke/session-timeline.spec.ts +++ b/packages/app/e2e/smoke/session-timeline.spec.ts @@ -1,4 +1,5 @@ import { expect, test, type Page } from "@playwright/test" +import { base64Encode } from "@opencode-ai/core/util/encode" import { fixture, pageMessages } from "./session-timeline.fixture" import { trackPageErrors, expectNoSmokeErrors } from "../utils/errors" import { mockOpenCodeServer } from "../utils/mock-server" @@ -37,12 +38,12 @@ test.describe("smoke: session timeline", () => { project: fixture.project, pageMessages, }) - await configureSmokePage(page) + await configureSmokePage(page, fixture.directory) - await openProject(page, "SmokeProject") - await navigateToSession(page, fixture.sourceID, fixture.expected.sourceTitle) - await expectSessionReady(page, "smoke-project") - await navigateToSession(page, fixture.targetID, fixture.expected.targetTitle) + await selectHomeProject(page, fixture.project.name) + await navigateToSession(page, fixture.directory, fixture.sourceID, fixture.expected.sourceTitle) + await expectSessionReady(page) + await navigateToSession(page, fixture.directory, fixture.targetID, fixture.expected.targetTitle) const expectedPartIDs = fixture.expected.targetPartIDs const expectedMessageIDs = fixture.expected.targetMessageIDs await expectSessionTimelineReady(page, expectedPartIDs, expectedMessageIDs, errors) @@ -50,7 +51,7 @@ test.describe("smoke: session timeline", () => { }) }) -async function configureSmokePage(page: Page) { +async function configureSmokePage(page: Page, directory: string) { await page.addInitScript(() => { localStorage.setItem( "settings.v3", @@ -63,7 +64,23 @@ async function configureSmokePage(page: Page) { }, }), ) + }) + await page.addInitScript((directory) => { + localStorage.setItem( + "opencode.global.dat:server", + JSON.stringify({ + projects: { + local: [{ worktree: directory, expanded: true }], + }, + lastProject: { + local: directory, + }, + }), + ) + }, directory) + + await page.addInitScript(() => { const smoke = window as SmokeWindow smoke.__timelineSmokeErrorToasts = [] smoke.__timelineSmokeForbiddenText = [] @@ -392,21 +409,20 @@ function expectCompleteScroll( expect(expectedPartIDs.length).toBe(331) } -async function openProject(page: Page, projectName: string) { +async function selectHomeProject(page: Page, projectName: string) { await page.goto("/") - await page.getByRole("button", { name: new RegExp(projectName, "i") }).click() + await page + .locator('[data-component="home-project-row"]') + .filter({ hasText: new RegExp(projectName, "i") }) + .click() + await expect(page).toHaveURL(/\/$/) } -async function navigateToSession(page: Page, sessionId: string, expectedTitle: string) { - // Use evaluate to click to avoid strict visibility/animation issues during rapid e2e navigation - await page - .locator(`a[href*="${sessionId}"]`) - .first() - .evaluate((el) => (el as HTMLElement).click()) +async function navigateToSession(page: Page, directory: string, sessionId: string, expectedTitle: string) { + await page.goto(`/${base64Encode(directory)}/session/${sessionId}`) await expect(page.getByRole("heading", { name: expectedTitle })).toBeVisible() } -async function expectSessionReady(page: Page, projectName: string) { - await expect(page.getByText(projectName).first()).toBeVisible() - await expect(page.getByText("Ask anything...")).toBeVisible() +async function expectSessionReady(page: Page) { + await expect(page.getByRole("textbox", { name: /Ask anything/i })).toBeVisible() } diff --git a/packages/app/e2e/utils/mock-server.ts b/packages/app/e2e/utils/mock-server.ts index b89f46deea61..9a03a9d5adb1 100644 --- a/packages/app/e2e/utils/mock-server.ts +++ b/packages/app/e2e/utils/mock-server.ts @@ -18,6 +18,7 @@ export interface MockServerConfig { project: unknown sessions: ({ id: string } & Record)[] pageMessages: (sessionId: string, limit: number, before?: string) => { items: unknown[]; cursor?: string } + events?: () => unknown[] } export async function mockOpenCodeServer(page: Page, config: MockServerConfig) { @@ -43,7 +44,8 @@ export async function mockOpenCodeServer(page: Page, config: MockServerConfig) { if (url.port !== targetPort) return route.fallback() const path = url.pathname - if (path === "/global/event" || path === "/event") return sse(route) + if (path === "/global/event" || path === "/event") return sse(route, config.events?.()) + if (path === "/global/health") return json(route, { healthy: true }) if (emptyObject.has(path)) return json(route, {}) if (emptyList.has(path)) return json(route, []) if (path in staticRoutes) return json(route, staticRoutes[path]) @@ -81,6 +83,10 @@ function json(route: Route, body: unknown, headers?: Record) { }) } -function sse(route: Route) { - return route.fulfill({ status: 200, contentType: "text/event-stream", body: ": ok\n\n" }) +function sse(route: Route, events?: unknown[]) { + return route.fulfill({ + status: 200, + contentType: "text/event-stream", + body: events?.map((event) => `data: ${JSON.stringify(event)}\n\n`).join("") || ": ok\n\n", + }) } diff --git a/packages/app/package.json b/packages/app/package.json index e24428e5ff28..cefda5301bbd 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "1.15.5", + "version": "1.15.12", "description": "", "type": "module", "exports": { @@ -42,10 +42,10 @@ }, "dependencies": { "@kobalte/core": "catalog:", - "@sentry/solid": "catalog:", + "@opencode-ai/core": "workspace:*", "@opencode-ai/sdk": "workspace:*", "@opencode-ai/ui": "workspace:*", - "@opencode-ai/core": "workspace:*", + "@sentry/solid": "catalog:", "@shikijs/transformers": "3.9.2", "@solid-primitives/active-element": "2.1.3", "@solid-primitives/audio": "1.4.2", @@ -54,6 +54,7 @@ "@solid-primitives/i18n": "2.2.1", "@solid-primitives/media": "2.3.3", "@solid-primitives/resize-observer": "2.1.5", + "@solid-primitives/scheduled": "1.5.3", "@solid-primitives/scroll": "2.1.3", "@solid-primitives/storage": "catalog:", "@solid-primitives/timer": "1.4.4", diff --git a/packages/app/public/assets/Inter.ttf b/packages/app/public/assets/Inter.ttf new file mode 100644 index 000000000000..e31b51e3e938 Binary files /dev/null and b/packages/app/public/assets/Inter.ttf differ diff --git a/packages/app/src/app.tsx b/packages/app/src/app.tsx index 3189d80257df..9554a6363112 100644 --- a/packages/app/src/app.tsx +++ b/packages/app/src/app.tsx @@ -14,6 +14,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/solid-query" import { Effect } from "effect" import { type Component, + createEffect, createMemo, createResource, createSignal, @@ -30,8 +31,8 @@ import { Dynamic } from "solid-js/web" import { CommandProvider } from "@/context/command" import { CommentsProvider } from "@/context/comments" import { FileProvider } from "@/context/file" -import { GlobalSDKProvider } from "@/context/global-sdk" -import { GlobalSyncProvider } from "@/context/global-sync" +import { ServerSDKProvider } from "@/context/server-sdk" +import { ServerSyncProvider } from "@/context/server-sync" import { HighlightsProvider } from "@/context/highlights" import { LanguageProvider, type Locale, useLanguage } from "@/context/language" import { LayoutProvider } from "@/context/layout" @@ -40,30 +41,26 @@ import { NotificationProvider } from "@/context/notification" import { PermissionProvider } from "@/context/permission" import { PromptProvider } from "@/context/prompt" import { ServerConnection, ServerProvider, serverName, useServer } from "@/context/server" -import { SettingsProvider } from "@/context/settings" +import { SettingsProvider, useSettings } from "@/context/settings" import { TerminalProvider } from "@/context/terminal" import DirectoryLayout from "@/pages/directory-layout" import Layout from "@/pages/layout" import { ErrorPage } from "./pages/error" import { useCheckServerHealth } from "./utils/server-health" +import { ServersProvider } from "./context/servers" const HomeRoute = lazy(() => import("@/pages/home")) -const loadSession = () => import("@/pages/session") -const Session = lazy(loadSession) -const Loading = () =>
+const Session = lazy(() => import("@/pages/session")) -if (typeof location === "object" && /\/session(?:\/|$)/.test(location.pathname)) { - void loadSession() -} - -const SessionRoute = () => ( - - - +const SessionRoute = Object.assign( + () => ( + + + + ), + { preload: Session.preload }, ) -const SessionIndexRoute = () => - function UiI18nBridge(props: ParentProps) { const language = useLanguage() return {props.children} @@ -78,6 +75,7 @@ declare global { } api?: { setTitlebar?: (theme: { mode: "light" | "dark" }) => Promise + exportDebugLogs?: () => Promise } } } @@ -95,9 +93,26 @@ function QueryProvider(props: ParentProps) { return {props.children} } +function BodyDesignClass() { + const settings = useSettings() + + createEffect(() => { + if (typeof document === "undefined") return + + const enabled = settings.general.newLayoutDesigns() + document.body.classList.toggle("text-12-regular", !enabled) + document.body.classList.toggle("font-(family-name:--font-family-text)", enabled) + document.body.classList.toggle("text-[13px]", enabled) + document.body.classList.toggle("font-[440]", enabled) + }) + + return null +} + function AppShellProviders(props: ParentProps) { return ( + @@ -300,31 +315,29 @@ export function AppInterface(props: { disableHealthCheck?: boolean }) { return ( - - - - - - - {routerProps.children}} - > - - - - - - - - - - - + + + + + + + + {routerProps.children}} + > + + + } /> + + + + + + + + + ) } diff --git a/packages/app/src/components/dialog-connect-provider.tsx b/packages/app/src/components/dialog-connect-provider.tsx index e305743799af..a0ccc161f25f 100644 --- a/packages/app/src/components/dialog-connect-provider.tsx +++ b/packages/app/src/components/dialog-connect-provider.tsx @@ -12,15 +12,15 @@ import { showToast } from "@opencode-ai/ui/toast" import { createEffect, createMemo, createResource, Match, onCleanup, onMount, Switch } from "solid-js" import { createStore, produce } from "solid-js/store" import { Link } from "@/components/link" -import { useGlobalSDK } from "@/context/global-sdk" -import { useGlobalSync } from "@/context/global-sync" +import { useServerSDK } from "@/context/server-sdk" +import { useServerSync } from "@/context/server-sync" import { useLanguage } from "@/context/language" import { useProviders } from "@/hooks/use-providers" export function DialogConnectProvider(props: { provider: string }) { const dialog = useDialog() - const globalSync = useGlobalSync() - const globalSDK = useGlobalSDK() + const serverSync = useServerSync() + const serverSDK = useServerSDK() const language = useLanguage() const providers = useProviders() @@ -41,9 +41,7 @@ export function DialogConnectProvider(props: { provider: string }) { }) const provider = createMemo( - () => - providers.all().find((x) => x.id === props.provider) ?? - globalSync.data.provider.all.find((x) => x.id === props.provider)!, + () => providers.all().get(props.provider) ?? serverSync.data.provider.all.get(props.provider)!, ) const fallback = createMemo(() => [ { @@ -54,16 +52,16 @@ export function DialogConnectProvider(props: { provider: string }) { const [auth] = createResource( () => props.provider, async () => { - const cached = globalSync.data.provider_auth[props.provider] + const cached = serverSync.data.provider_auth[props.provider] if (cached) return cached - const res = await globalSDK.client.provider.auth() + const res = await serverSDK.client.provider.auth() if (!alive.value) return fallback() - globalSync.set("provider_auth", res.data ?? {}) + serverSync.set("provider_auth", res.data ?? {}) return res.data?.[props.provider] ?? fallback() }, ) - const loading = createMemo(() => auth.loading && !globalSync.data.provider_auth[props.provider]) - const methods = createMemo(() => auth.latest ?? globalSync.data.provider_auth[props.provider] ?? fallback()) + const loading = createMemo(() => auth.loading && !serverSync.data.provider_auth[props.provider]) + const methods = createMemo(() => auth.latest ?? serverSync.data.provider_auth[props.provider] ?? fallback()) const [store, setStore] = createStore({ methodIndex: undefined as undefined | number, authorization: undefined as undefined | ProviderAuthAuthorization, @@ -160,7 +158,7 @@ export function DialogConnectProvider(props: { provider: string }) { } dispatch({ type: "auth.pending" }) const start = Date.now() - await globalSDK.client.provider.oauth + await serverSDK.client.provider.oauth .authorize( { providerID: props.provider, @@ -332,7 +330,7 @@ export function DialogConnectProvider(props: { provider: string }) { }) async function complete() { - await globalSDK.client.global.dispose() + await serverSDK.client.global.dispose() dialog.close() showToast({ variant: "success", @@ -409,7 +407,7 @@ export function DialogConnectProvider(props: { provider: string }) { } setFormStore("error", undefined) - await globalSDK.client.auth.set({ + await serverSDK.client.auth.set({ providerID: props.provider, auth: { type: "api", @@ -480,7 +478,7 @@ export function DialogConnectProvider(props: { provider: string }) { } setFormStore("error", undefined) - const result = await globalSDK.client.provider.oauth + const result = await serverSDK.client.provider.oauth .callback({ providerID: props.provider, method: store.methodIndex, @@ -526,14 +524,14 @@ export function DialogConnectProvider(props: { provider: string }) { const code = createMemo(() => { const instructions = store.authorization?.instructions if (instructions?.includes(":")) { - return instructions.split(":")[1]?.trim() + return instructions.split(":").pop()?.trim() } return instructions }) onMount(() => { void (async () => { - const result = await globalSDK.client.provider.oauth + const result = await serverSDK.client.provider.oauth .callback({ providerID: props.provider, method: store.methodIndex, diff --git a/packages/app/src/components/dialog-custom-provider.tsx b/packages/app/src/components/dialog-custom-provider.tsx index 53b66fb451d3..ad30236b0410 100644 --- a/packages/app/src/components/dialog-custom-provider.tsx +++ b/packages/app/src/components/dialog-custom-provider.tsx @@ -9,8 +9,8 @@ import { showToast } from "@opencode-ai/ui/toast" import { batch, For } from "solid-js" import { createStore, produce } from "solid-js/store" import { Link } from "@/components/link" -import { useGlobalSDK } from "@/context/global-sdk" -import { useGlobalSync } from "@/context/global-sync" +import { useServerSDK } from "@/context/server-sdk" +import { useServerSync } from "@/context/server-sync" import { useLanguage } from "@/context/language" import { type FormState, headerRow, modelRow, validateCustomProvider } from "./dialog-custom-provider-form" import { DialogSelectProvider } from "./dialog-select-provider" @@ -21,8 +21,8 @@ type Props = { export function DialogCustomProvider(props: Props) { const dialog = useDialog() - const globalSync = useGlobalSync() - const globalSDK = useGlobalSDK() + const serverSync = useServerSync() + const serverSDK = useServerSDK() const language = useLanguage() const [form, setForm] = createStore({ @@ -105,8 +105,8 @@ export function DialogCustomProvider(props: Props) { const output = validateCustomProvider({ form, t: language.t, - disabledProviders: globalSync.data.config.disabled_providers ?? [], - existingProviderIDs: new Set(globalSync.data.provider.all.map((p) => p.id)), + disabledProviders: serverSync.data.config.disabled_providers ?? [], + existingProviderIDs: new Set(serverSync.data.provider.all.keys()), }) batch(() => { setForm("err", output.err) @@ -118,11 +118,11 @@ export function DialogCustomProvider(props: Props) { const saveMutation = useMutation(() => ({ mutationFn: async (result: NonNullable>) => { - const disabledProviders = globalSync.data.config.disabled_providers ?? [] + const disabledProviders = serverSync.data.config.disabled_providers ?? [] const nextDisabled = disabledProviders.filter((id) => id !== result.providerID) if (result.key) { - await globalSDK.client.auth.set({ + await serverSDK.client.auth.set({ providerID: result.providerID, auth: { type: "api", @@ -131,7 +131,7 @@ export function DialogCustomProvider(props: Props) { }) } - await globalSync.updateConfig({ + await serverSync.updateConfig({ provider: { [result.providerID]: result.config }, disabled_providers: nextDisabled, }) diff --git a/packages/app/src/components/dialog-edit-project.tsx b/packages/app/src/components/dialog-edit-project.tsx index b4b69246cbdd..21677b72e39a 100644 --- a/packages/app/src/components/dialog-edit-project.tsx +++ b/packages/app/src/components/dialog-edit-project.tsx @@ -6,20 +6,20 @@ import { useMutation } from "@tanstack/solid-query" import { Icon } from "@opencode-ai/ui/icon" import { createMemo, For, Show } from "solid-js" import { createStore } from "solid-js/store" -import { useGlobalSDK } from "@/context/global-sdk" -import { useGlobalSync } from "@/context/global-sync" +import { useServerSDK } from "@/context/server-sdk" +import { useServerSync } from "@/context/server-sync" import { type LocalProject, getAvatarColors } from "@/context/layout" import { getFilename } from "@opencode-ai/core/util/path" import { Avatar } from "@opencode-ai/ui/avatar" import { useLanguage } from "@/context/language" -import { getProjectAvatarSource } from "@/pages/layout/sidebar-items" +import { getProjectAvatarSource } from "@/pages/layout/helpers" const AVATAR_COLOR_KEYS = ["pink", "mint", "orange", "purple", "cyan", "lime"] as const export function DialogEditProject(props: { project: LocalProject }) { const dialog = useDialog() - const globalSDK = useGlobalSDK() - const globalSync = useGlobalSync() + const serverSDK = useServerSDK() + const serverSync = useServerSync() const language = useLanguage() const folderName = createMemo(() => getFilename(props.project.worktree)) @@ -78,19 +78,19 @@ export function DialogEditProject(props: { project: LocalProject }) { const start = store.startup.trim() if (props.project.id && props.project.id !== "global") { - await globalSDK.client.project.update({ + await serverSDK.client.project.update({ projectID: props.project.id, directory: props.project.worktree, name, icon: { color: store.color || "", override: store.iconOverride || "" }, commands: { start }, }) - globalSync.project.icon(props.project.worktree, store.iconOverride || undefined) + serverSync.project.icon(props.project.worktree, store.iconOverride || undefined) dialog.close() return } - globalSync.project.meta(props.project.worktree, { + serverSync.project.meta(props.project.worktree, { name, icon: { color: store.color || undefined, override: store.iconOverride || undefined }, commands: { start: start || undefined }, diff --git a/packages/app/src/components/dialog-select-directory.tsx b/packages/app/src/components/dialog-select-directory.tsx index 005d28709161..c7c3b5098665 100644 --- a/packages/app/src/components/dialog-select-directory.tsx +++ b/packages/app/src/components/dialog-select-directory.tsx @@ -6,8 +6,8 @@ import type { ListRef } from "@opencode-ai/ui/list" import { getDirectory, getFilename } from "@opencode-ai/core/util/path" import fuzzysort from "fuzzysort" import { createMemo, createResource, createSignal } from "solid-js" -import { useGlobalSDK } from "@/context/global-sdk" -import { useGlobalSync } from "@/context/global-sync" +import { useServerSDK } from "@/context/server-sdk" +import { useServerSync } from "@/context/server-sync" import { useLayout } from "@/context/layout" import { useLanguage } from "@/context/language" @@ -128,7 +128,7 @@ function uniqueRows(rows: Row[]) { } function useDirectorySearch(args: { - sdk: ReturnType + sdk: ReturnType start: () => string | undefined home: () => string }) { @@ -246,8 +246,8 @@ function useDirectorySearch(args: { } export function DialogSelectDirectory(props: DialogSelectDirectoryProps) { - const sync = useGlobalSync() - const sdk = useGlobalSDK() + const sync = useServerSync() + const sdk = useServerSDK() const layout = useLayout() const dialog = useDialog() const language = useLanguage() diff --git a/packages/app/src/components/dialog-select-file.tsx b/packages/app/src/components/dialog-select-file.tsx index ac3bc03e44ec..835ace6613e3 100644 --- a/packages/app/src/components/dialog-select-file.tsx +++ b/packages/app/src/components/dialog-select-file.tsx @@ -9,8 +9,8 @@ import { getDirectory, getFilename } from "@opencode-ai/core/util/path" import { useNavigate } from "@solidjs/router" import { createMemo, createSignal, Match, onCleanup, Show, Switch } from "solid-js" import { formatKeybind, useCommand, type CommandOption } from "@/context/command" -import { useGlobalSDK } from "@/context/global-sdk" -import { useGlobalSync } from "@/context/global-sync" +import { useServerSDK } from "@/context/server-sdk" +import { useServerSync } from "@/context/server-sync" import { useLayout } from "@/context/layout" import { useFile } from "@/context/file" import { useLanguage } from "@/context/language" @@ -175,7 +175,7 @@ function createFileEntries(props: { function createSessionEntries(props: { workspaces: () => string[] label: (directory: string) => string - globalSDK: ReturnType + serverSDK: ReturnType language: ReturnType }) { const state: { @@ -207,7 +207,7 @@ function createSessionEntries(props: { state.inflight = Promise.all( dirs.map((directory) => { const description = props.label(directory) - return props.globalSDK.client.session + return props.serverSDK.client.session .list({ directory, roots: true }) .then((x) => (x.data ?? []) @@ -268,8 +268,8 @@ export function DialogSelectFile(props: { mode?: DialogSelectFileMode; onOpenFil const file = useFile() const dialog = useDialog() const navigate = useNavigate() - const globalSDK = useGlobalSDK() - const globalSync = useGlobalSync() + const serverSDK = useServerSDK() + const serverSync = useServerSync() const { params, tabs, view } = useSessionLayout() const filesOnly = () => props.mode === "files" const state = { cleanup: undefined as (() => void) | void, committed: false } @@ -292,21 +292,21 @@ export function DialogSelectFile(props: { mode?: DialogSelectFileMode; onOpenFil if (directory && !dirs.includes(directory)) return [...dirs, directory] return dirs }) - const homedir = createMemo(() => globalSync.data.path.home) + const homedir = createMemo(() => serverSync.data.path.home) const label = (directory: string) => { const current = project() const kind = current && directory === current.worktree ? language.t("workspace.type.local") : language.t("workspace.type.sandbox") - const [store] = globalSync.child(directory, { bootstrap: false }) + const [store] = serverSync.child(directory, { bootstrap: false }) const home = homedir() const path = home ? directory.replace(home, "~") : directory const name = store.vcs?.branch ?? getFilename(directory) return `${kind} : ${name || path}` } - const { sessions } = createSessionEntries({ workspaces, label, globalSDK, language }) + const { sessions } = createSessionEntries({ workspaces, label, serverSDK, language }) const items = async (text: string) => { const query = text.trim() diff --git a/packages/app/src/components/dialog-select-mcp.tsx b/packages/app/src/components/dialog-select-mcp.tsx index 5a28173ead80..77cfcc039ca5 100644 --- a/packages/app/src/components/dialog-select-mcp.tsx +++ b/packages/app/src/components/dialog-select-mcp.tsx @@ -6,7 +6,7 @@ import { Dialog } from "@opencode-ai/ui/dialog" import { List } from "@opencode-ai/ui/list" import { Switch } from "@opencode-ai/ui/switch" import { useLanguage } from "@/context/language" -import { useQueryOptions } from "@/context/global-sync" +import { useQueryOptions } from "@/context/server-sync" import { pathKey } from "@/utils/path-key" const statusLabels = { diff --git a/packages/app/src/components/dialog-select-model-unpaid.tsx b/packages/app/src/components/dialog-select-model-unpaid.tsx index e25e8f0c17de..f916ef62308d 100644 --- a/packages/app/src/components/dialog-select-model-unpaid.tsx +++ b/packages/app/src/components/dialog-select-model-unpaid.tsx @@ -91,7 +91,7 @@ export const DialogSelectModelUnpaid: Component<{ model?: ModelState }> = (props
x?.id} + key={(p) => p.id} items={providers.popular} activeIcon="plus-small" sortBy={(a, b) => { diff --git a/packages/app/src/components/dialog-select-provider.tsx b/packages/app/src/components/dialog-select-provider.tsx index e53738399aba..1273db596fcd 100644 --- a/packages/app/src/components/dialog-select-provider.tsx +++ b/packages/app/src/components/dialog-select-provider.tsx @@ -35,7 +35,7 @@ export const DialogSelectProvider: Component = () => { key={(x) => x?.id} items={() => { language.locale() - return [{ id: CUSTOM_ID, name: customLabel() }, ...providers.all()] + return [{ id: CUSTOM_ID, name: customLabel() }, ...providers.all().values()] }} filterKeys={["id", "name"]} groupBy={(x) => (popularProviders.includes(x.id) ? popularGroup() : otherGroup())} diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index e07b2f186455..84fe7495f874 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -1,6 +1,22 @@ import { useFilteredList } from "@opencode-ai/ui/hooks" import { useSpring } from "@opencode-ai/ui/motion-spring" -import { createEffect, on, Component, Show, onCleanup, createMemo, createSignal, createResource } from "solid-js" +import { + createEffect, + on, + Component, + splitProps, + For, + Show, + onCleanup, + createMemo, + createSignal, + createResource, + Switch, + Match, + type ComponentProps, + type JSX, +} from "solid-js" +import { Popover as KobaltePopover } from "@kobalte/core/popover" import { createStore } from "solid-js/store" import { useLocal } from "@/context/local" import { selectionFromLines, type SelectedLineRange, useFile } from "@/context/file" @@ -15,12 +31,14 @@ import { FileAttachmentPart, } from "@/context/prompt" import { useLayout } from "@/context/layout" +import { useNavigate } from "@solidjs/router" import { useSDK } from "@/context/sdk" +import { useServer } from "@/context/server" import { useSync } from "@/context/sync" import { useComments } from "@/context/comments" import { Button } from "@opencode-ai/ui/button" import { DockShellForm, DockTray } from "@opencode-ai/ui/dock-surface" -import { Icon } from "@opencode-ai/ui/icon" +import { Icon, type IconProps } from "@opencode-ai/ui/icon" import { ProviderIcon } from "@opencode-ai/ui/provider-icon" import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip" import { IconButton } from "@opencode-ai/ui/icon-button" @@ -33,6 +51,7 @@ import { Persist, persisted } from "@/utils/persist" import { usePermission } from "@/context/permission" import { useLanguage } from "@/context/language" import { usePlatform } from "@/context/platform" +import { useSettings } from "@/context/settings" import { useSessionLayout } from "@/pages/session/session-layout" import { createSessionTabs } from "@/pages/session/helpers" import { createTextFragment, getCursorPosition, setCursorPosition, setRangeEdge } from "./prompt-input/editor-dom" @@ -55,11 +74,14 @@ import { PromptDragOverlay } from "./prompt-input/drag-overlay" import { promptPlaceholder } from "./prompt-input/placeholder" import { ImagePreview } from "@opencode-ai/ui/image-preview" import { useQueries } from "@tanstack/solid-query" -import { useQueryOptions } from "@/context/global-sync" +import { useQueryOptions } from "@/context/server-sync" import { pathKey } from "@/utils/path-key" +import { base64Encode } from "@opencode-ai/core/util/encode" +import { displayName } from "@/pages/layout/helpers" interface PromptInputProps { class?: string + variant?: "dock" | "new-session" ref?: (el: HTMLDivElement) => void newSessionWorktree?: string onNewSessionWorktreeReset?: () => void @@ -101,6 +123,7 @@ const EXAMPLES = [ export const PromptInput: Component = (props) => { const sdk = useSDK() + const navigate = useNavigate() const queryOptions = useQueryOptions() const sync = useSync() @@ -108,6 +131,7 @@ export const PromptInput: Component = (props) => { const files = useFile() const prompt = usePrompt() const layout = useLayout() + const server = useServer() const comments = useComments() const dialog = useDialog() const providers = useProviders() @@ -115,11 +139,13 @@ export const PromptInput: Component = (props) => { const permission = usePermission() const language = useLanguage() const platform = usePlatform() + const settings = useSettings() const { params, tabs, view } = useSessionLayout() let editorRef!: HTMLDivElement let fileInputRef: HTMLInputElement | undefined let scrollRef!: HTMLDivElement let slashPopoverRef!: HTMLDivElement + let projectSearchRef: HTMLInputElement | undefined const mirror = { input: false } const inset = 56 @@ -260,6 +286,10 @@ export const PromptInput: Component = (props) => { mode: "normal", applyingHistory: false, }) + const [picker, setPicker] = createStore({ + projectOpen: false, + projectSearch: "", + }) const buttonsSpring = useSpring(() => (store.mode === "normal" ? 1 : 0), { visualDuration: 0.2, bounce: 0 }) const motion = (value: number) => ({ @@ -1055,6 +1085,21 @@ export const PromptInput: Component = (props) => { readClipboardImage: platform.readClipboardImage, }) + const fileAttachmentInput = () => ( + (fileInputRef = el)} + type="file" + multiple + accept={ACCEPTED_FILE_TYPES.join(",")} + class="hidden" + onChange={(e) => { + const list = e.currentTarget.files + if (list) void addAttachments(Array.from(list)) + e.currentTarget.value = "" + }} + /> + ) + const variants = createMemo(() => ["default", ...local.model.variant.list()]) const accepting = createMemo(() => { const id = params.id @@ -1266,8 +1311,132 @@ export const PromptInput: Component = (props) => { (p) => p, ) + const designPlaceholder = () => { + if (store.mode === "shell") return placeholder() + return "Ask anything, / for commands, @ for context..." + } + + const modelControlState = createMemo(() => ({ + loading: providersLoading(), + paid: providers.paid().length > 0, + title: language.t("command.model.choose"), + keybind: command.keybind("model.choose"), + model: local.model, + providerID: local.model.current()?.provider?.id, + modelName: local.model.current()?.name ?? language.t("dialog.model.select.title"), + style: control(), + onClose: restoreFocus, + onUnpaidClick: () => { + void import("@/components/dialog-select-model-unpaid").then((x) => { + dialog.show(() => ) + }) + }, + })) + + const newSession = () => props.variant === "new-session" + const projects = createMemo(() => layout.projects.list()) + const projectForDirectory = (directory: string | undefined) => { + if (!directory) return + const key = pathKey(directory) + return projects().find( + (project) => pathKey(project.worktree) === key || project.sandboxes?.some((sandbox) => pathKey(sandbox) === key), + ) + } + const selectedProject = createMemo(() => projectForDirectory(sdk.directory)) + const projectResults = createMemo(() => { + const search = picker.projectSearch.trim().toLowerCase() + if (!search) return projects() + return projects().filter((project) => displayName(project).toLowerCase().includes(search)) + }) + const showAgentControl = createMemo(() => settings.general.showCustomAgents() && agentNames().length > 0) + const selectProject = (worktree: string) => { + setPicker({ + projectOpen: false, + projectSearch: "", + }) + if (pathKey(worktree) === pathKey(selectedProject()?.worktree ?? "")) { + restoreFocus() + return + } + layout.projects.open(worktree) + server.projects.touch(worktree) + navigate(`/${base64Encode(worktree)}/session`) + } + const addProject = async () => { + const select = (result: string | string[] | null) => { + const directory = Array.isArray(result) ? result[0] : result + if (!directory) return + selectProject(directory) + } + if (platform.openDirectoryPickerDialog && server.isLocal()) { + select(await platform.openDirectoryPickerDialog({ title: language.t("command.project.open") })) + return + } + void import("@/components/dialog-select-directory").then((x) => { + dialog.show( + () => , + () => select(null), + ) + }) + } + + const projectPickerState = createMemo(() => ({ + open: picker.projectOpen, + trigger: { + action: "prompt-project", + icon: "folder", + label: selectedProject() ? displayName(selectedProject()!) : language.t("session.new.project.new"), + class: "max-w-[203px]", + style: control(), + onPress: () => setPicker("projectOpen", true), + }, + search: picker.projectSearch, + searchPlaceholder: language.t("session.new.project.search"), + clearLabel: language.t("common.clear"), + items: projectResults().map((project) => ({ + icon: "folder", + label: displayName(project), + selected: selectedProject()?.worktree === project.worktree, + onSelect: () => selectProject(project.worktree), + })), + action: { + icon: "plus", + label: language.t("session.new.project.add"), + onSelect: () => { + setPicker("projectOpen", false) + void addProject() + }, + }, + onOpenChange: (open) => { + setPicker("projectOpen", open) + if (open) requestAnimationFrame(() => projectSearchRef?.focus()) + }, + onSearchInput: (value) => setPicker("projectSearch", value), + onSearchClear: () => setPicker("projectSearch", ""), + searchRef: (el) => (projectSearchRef = el), + })) + const agentControlState = createMemo(() => ({ + title: language.t("command.agent.cycle"), + keybind: command.keybind("agent.cycle"), + options: agentNames(), + current: local.agent.current()?.name ?? "", + style: control(), + onSelect: (value) => { + local.agent.set(value) + restoreFocus() + }, + })) + const newProjectTriggerState = createMemo(() => ({ + action: "prompt-project", + icon: "folder-add-left", + label: language.t("session.new.project.new"), + class: "max-w-[160px]", + style: control(), + onPress: () => void addProject(), + })) + return ( -
+
{(promptReady(), null)} = (props) => { commandKeybind={command.keybind} t={(key) => language.t(key as Parameters[0])} /> - - - { - const active = comments.active() - return !!item.commentID && item.commentID === active?.id && item.path === active?.file - }} - openComment={openComment} - remove={(item) => { - if (item.commentID) comments.remove(item.path, item.commentID) - prompt.context.remove(item.key) - }} - t={(key) => language.t(key as Parameters[0])} - /> - - dialog.show(() => ) - } - onRemove={removeAttachment} - removeLabel={language.t("prompt.attachment.remove")} - /> -
{ - const target = e.target - if (!(target instanceof HTMLElement)) return - if (target.closest('[data-action="prompt-attach"], [data-action="prompt-submit"]')) { - return - } - editorRef?.focus() - }} - > -
(scrollRef = el)} - style={{ "scroll-padding-bottom": space }} - > -
{ - editorRef = el - props.ref?.(el) - }} - role="textbox" - aria-multiline="true" - aria-label={placeholder()} - contenteditable="true" - autocapitalize={store.mode === "normal" ? "sentences" : "off"} - autocorrect={store.mode === "normal" ? "on" : "off"} - spellcheck={store.mode === "normal"} - inputMode="text" - // @ts-expect-error - autocomplete="off" - onInput={handleInput} - onPaste={handlePaste} - onCompositionStart={handleCompositionStart} - onCompositionEnd={handleCompositionEnd} - onBlur={handleBlur} - onKeyDown={handleKeyDown} + + +
+ -
- {placeholder()} -
+ + { + const active = comments.active() + return !!item.commentID && item.commentID === active?.id && item.path === active?.file + }} + openComment={openComment} + remove={(item) => { + if (item.commentID) comments.remove(item.path, item.commentID) + prompt.context.remove(item.key) + }} + t={(key) => language.t(key as Parameters[0])} + /> + + dialog.show(() => ) + } + onRemove={removeAttachment} + removeLabel={language.t("prompt.attachment.remove")} + /> +
{ + const target = e.target + if (!(target instanceof HTMLElement)) return + if (target.closest('[data-action^="prompt-"]')) return + editorRef?.focus() + }} + > +
(scrollRef = el)}> +
{ + editorRef = el + props.ref?.(el) + }} + role="textbox" + aria-multiline="true" + aria-label={designPlaceholder()} + contenteditable="true" + autocapitalize={store.mode === "normal" ? "sentences" : "off"} + autocorrect={store.mode === "normal" ? "on" : "off"} + spellcheck={store.mode === "normal"} + inputMode="text" + // @ts-expect-error + autocomplete="off" + onInput={handleInput} + onPaste={handlePaste} + onCompositionStart={handleCompositionStart} + onCompositionEnd={handleCompositionEnd} + onBlur={handleBlur} + onKeyDown={handleKeyDown} + classList={{ + "select-text": true, + "min-h-[52px] w-full px-4 pt-4 pb-2 focus:outline-none whitespace-pre-wrap leading-5 text-[13px] font-[440] text-v2-text-text-base": true, + "[&_[data-type=file]]:text-syntax-property": true, + "[&_[data-type=agent]]:text-syntax-type": true, + "font-mono!": store.mode === "shell", + }} + /> +
+ {designPlaceholder()} +
+
+
+
+
+ {fileAttachmentInput()} + + + + + + + + + + +
+ + + +
+ + +
+ +
+
- - -
- - -
-
+ {placeholder()} +
+
+ -
- +
+ + + +
+
- + {language.t("prompt.mode.shell")} +
+
- - + + +
+ 0} + fallback={ + + + + } + > + + + + + + + {local.model.current()?.name ?? language.t("dialog.model.select.title")} + + + + + +
+ 2}> +
+ + props.state.onSearchInput(event.currentTarget.value)} + /> + + +
+ {(item) => }
- - +
+
+ +
+ + + + ) +} + +function ComposerAgentControl(props: { state: ComposerAgentControlState }) { + return ( +
+
+ +
+ + props.onInput(event.currentTarget.value)} + /> + + + + + ) +} + +function HomeEmptyState(props: { + icon: Parameters[0]["name"] + title: string + description: string + action: string + onAction: () => void +}) { + return ( +
+
+ +
+
+
{props.title}
+
{props.description}
+
+ + {props.action} + +
+ ) +} + +function HomeSessionGroupHeader(props: { title: string; onNewSession?: () => void }) { + const language = useLanguage() + return ( +
+ + + {(onNewSession) => ( + + {language.t("command.session.new")} + + )} + +
+ ) +} + +function HomeSessionRow(props: { record: HomeSessionRecord; openSession: (session: Session) => void }) { + const serverSync = useServerSync() + const notification = useNotification() + const permission = usePermission() + const [sessionStore] = serverSync.child(props.record.session.directory, { bootstrap: false }) + const title = createMemo(() => sessionTitle(props.record.session.title) || props.record.session.id) + const unseenCount = createMemo(() => notification.session.unseenCount(props.record.session.id)) + const hasError = createMemo(() => notification.session.unseenHasError(props.record.session.id)) + const hasPermissions = createMemo( + () => + !!sessionPermissionRequest(sessionStore.session, sessionStore.permission, props.record.session.id, (item) => { + return !permission.autoResponds(item, props.record.session.directory) + }), + ) + const isWorking = createMemo(() => { + if (hasPermissions()) return false + return sessionStore.session_working(props.record.session.id) + }) + const tint = createMemo(() => messageAgentColor(sessionStore.message[props.record.session.id], sessionStore.agent)) + const showStatus = createMemo(() => isWorking() || hasPermissions() || hasError() || unseenCount() > 0) + + return ( + + ) +} + +function HomeSessionSkeleton(props: { label: string }) { + return ( +
+
+ +
+ + ) +} + +function groupSessions(records: HomeSessionRecord[], language: ReturnType): HomeSessionGroup[] { + const now = DateTime.local() + const yesterday = now.minus({ days: 1 }) + const todaySessions = records.filter((record) => + DateTime.fromMillis(record.session.time.updated ?? record.session.time.created).hasSame(now, "day"), + ) + const yesterdaySessions = records.filter((record) => + DateTime.fromMillis(record.session.time.updated ?? record.session.time.created).hasSame(yesterday, "day"), + ) + const olderSessions = records.filter((record) => { + const time = DateTime.fromMillis(record.session.time.updated ?? record.session.time.created) + return !time.hasSame(now, "day") && !time.hasSame(yesterday, "day") + }) + const olderTitle = + todaySessions.length === 0 && yesterdaySessions.length === 0 + ? language.t("sidebar.project.recentSessions") + : language.t("home.sessions.group.older") + + return [ + { id: "today" as const, title: language.t("home.sessions.group.today"), sessions: todaySessions }, + { id: "yesterday" as const, title: language.t("home.sessions.group.yesterday"), sessions: yesterdaySessions }, + { id: "older" as const, title: olderTitle, sessions: olderSessions }, + ].filter((group) => group.sessions.length > 0) +} + +function LegacyHome() { + const sync = useServerSync() + const layout = useLayout() + const platform = usePlatform() + const dialog = useDialog() + const navigate = useNavigate() + const servers = useServers() + const server = useServer() + const language = useLanguage() const homedir = createMemo(() => sync.data.path.home) const recent = createMemo(() => { return sync.data.project @@ -31,7 +696,7 @@ export default function Home() { }) const serverDotClass = createMemo(() => { - const healthy = server.healthy() + const healthy = servers.health[server.key]?.healthy if (healthy === true) return "bg-icon-success-base" if (healthy === false) return "bg-icon-critical-base" return "bg-border-weak-base" @@ -137,3 +802,50 @@ export default function Home() {
) } + +function ProjectList(props: { + projects: LocalProject[] + selectedProject?: string + onSelectedProjectChange?(project: string): void + onChooseProject?(): void + openNewSession: (directory: string) => void + editProject: (project: LocalProject) => void + closeProject: (directory: string) => void + clearNotifications: (project: LocalProject) => void + unseenCount: (project: LocalProject) => number + language: ReturnType +}) { + return ( + 0} + fallback={ + + } + > +
+ + {(project) => ( + props.onSelectedProjectChange?.(directory)} + openNewSession={props.openNewSession} + editProject={props.editProject} + closeProject={props.closeProject} + clearNotifications={props.clearNotifications} + language={props.language} + /> + )} + +
+
+ ) +} diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index 31d3e5dccdc2..70154a34de7f 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -14,8 +14,9 @@ import { } from "solid-js" import { makeEventListener } from "@solid-primitives/event-listener" import { useLocation, useNavigate, useParams } from "@solidjs/router" +import { useQuery } from "@tanstack/solid-query" import { useLayout, LocalProject } from "@/context/layout" -import { useGlobalSync } from "@/context/global-sync" +import { useServerSync } from "@/context/server-sync" import { Persist, persisted } from "@/utils/persist" import { base64Encode } from "@opencode-ai/core/util/encode" import { decode64 } from "@/utils/base64" @@ -34,7 +35,7 @@ import { DragDropProvider, DragDropSensors, DragOverlay, SortableProvider, close import type { DragEvent } from "@thisbeyond/solid-dnd" import { useProviders } from "@/hooks/use-providers" import { showToast, Toast, toaster } from "@opencode-ai/ui/toast" -import { useGlobalSDK } from "@/context/global-sdk" +import { useServerSDK } from "@/context/server-sdk" import { clearWorkspaceTerminals, getTerminalServerScope } from "@/context/terminal" import { dropSessionCaches, pickSessionCacheEvictions } from "@/context/global-sync/session-cache" import { @@ -61,7 +62,7 @@ import { useTheme, type ColorScheme } from "@opencode-ai/ui/theme/context" import { useCommand, type CommandOption } from "@/context/command" import { ConstrainDragXAxis, getDraggableId } from "@/utils/solid-dnd" import { DebugBar } from "@/components/debug-bar" -import { Titlebar } from "@/components/titlebar" +import { Titlebar, type TitlebarUpdate } from "@/components/titlebar" import { useServer } from "@/context/server" import { useLanguage, type Locale } from "@/context/language" import { pathKey } from "@/utils/path-key" @@ -110,8 +111,8 @@ export default function Layout(props: ParentProps) { let dialogDead = false const params = useParams() - const globalSDK = useGlobalSDK() - const globalSync = useGlobalSync() + const serverSDK = useServerSDK() + const serverSync = useServerSync() const layout = useLayout() const layoutReady = createMemo(() => layout.ready()) const platform = usePlatform() @@ -126,6 +127,7 @@ export default function Layout(props: ParentProps) { const command = useCommand() const theme = useTheme() const language = useLanguage() + const newDesign = createMemo(() => settings.general.newLayoutDesigns()) const initialDirectory = decode64(params.dir) const location = useLocation() const route = createMemo(() => { @@ -133,7 +135,7 @@ export default function Layout(props: ParentProps) { if (!slug) return { slug, dir: "" } const dir = decode64(slug) if (!dir) return { slug, dir: "" } - const store = globalSync.peek(dir, { bootstrap: false }) + const store = serverSync.peek(dir, { bootstrap: false }) return { slug, store, @@ -151,7 +153,7 @@ export default function Layout(props: ParentProps) { const currentDir = createMemo(() => route().dir) const [state, setState] = createStore({ - autoselect: !initialDirectory, + autoselect: !initialDirectory && !newDesign(), busyWorkspaces: {} as Record, hoverProject: undefined as string | undefined, scrollSessionKey: undefined as string | undefined, @@ -162,6 +164,35 @@ export default function Layout(props: ParentProps) { peeked: false, }) + const [update, setUpdate] = createStore({ + installing: false, + }) + const updateQuery = useQuery(() => ({ + queryKey: ["desktop", "update"] as const, + enabled: () => + !!platform.checkUpdate && !!platform.updateAndRestart && settings.ready() && settings.updates.startup(), + queryFn: () => platform.checkUpdate?.() ?? Promise.resolve({ updateAvailable: false, version: undefined }), + refetchInterval: (query) => (query.state.data?.updateAvailable ? false : 10 * 60 * 1000), + })) + const updateVersion = () => { + if (!settings.ready()) return + if (!settings.updates.startup()) return + if (!updateQuery.data?.updateAvailable) return + return updateQuery.data.version ?? "" + } + const installUpdate = () => { + if (!platform.updateAndRestart) return + setUpdate("installing", true) + void platform.updateAndRestart().catch(() => { + setUpdate("installing", false) + }) + } + const titlebarUpdate: TitlebarUpdate = { + version: updateVersion, + installing: () => update.installing, + install: installUpdate, + } + const editor = createInlineEditorController() const setBusy = (directory: string, value: boolean) => { const key = pathKey(directory) @@ -194,7 +225,7 @@ export default function Layout(props: ParentProps) { active: () => state.hoverProject, el: () => state.nav?.querySelector("[data-component='sidebar-rail']") ?? state.nav, onActivate: (directory) => { - globalSync.child(directory) + serverSync.child(directory) setState("hoverProject", directory) }, }) @@ -364,58 +395,6 @@ export default function Layout(props: ParentProps) { setLocale(next) } - const useUpdatePolling = () => - onMount(() => { - if (!platform.checkUpdate || !platform.updateAndRestart) return - - let toastId: number | undefined - let interval: ReturnType | undefined - - const pollUpdate = () => - platform.checkUpdate!().then(({ updateAvailable, version }) => { - if (!updateAvailable) return - if (toastId !== undefined) return - toastId = showToast({ - persistent: true, - icon: "download", - title: language.t("toast.update.title"), - description: language.t("toast.update.description", { version: version ?? "" }), - actions: [ - { - label: language.t("toast.update.action.installRestart"), - onClick: async () => { - await platform.updateAndRestart!() - }, - }, - { - label: language.t("toast.update.action.notYet"), - onClick: "dismiss", - }, - ], - }) - }) - - createEffect(() => { - if (!settings.ready()) return - - if (!settings.updates.startup()) { - if (interval === undefined) return - clearInterval(interval) - interval = undefined - return - } - - if (interval !== undefined) return - void pollUpdate() - interval = setInterval(pollUpdate, 10 * 60 * 1000) - }) - - onCleanup(() => { - if (interval === undefined) return - clearInterval(interval) - }) - }) - const useSDKNotificationToasts = () => onMount(() => { const toastBySession = new Map() @@ -430,7 +409,7 @@ export default function Layout(props: ParentProps) { alertedAtBySession.delete(sessionKey) } - const unsub = globalSDK.event.listen((e) => { + const unsub = serverSDK.event.listen((e) => { if (e.details?.type === "worktree.ready") { setBusy(e.name, false) WorktreeState.ready(e.name) @@ -464,7 +443,7 @@ export default function Layout(props: ParentProps) { const props = e.details.properties if (e.details.type === "permission.asked" && permission.autoResponds(e.details.properties, directory)) return - const [store] = globalSync.child(directory, { bootstrap: false }) + const [store] = serverSync.child(directory, { bootstrap: false }) const session = store.session.find((s) => s.id === props.sessionID) const sessionKey = `${directory}:${props.sessionID}` @@ -527,7 +506,7 @@ export default function Layout(props: ParentProps) { if (!currentDir() || !currentSession) return const sessionKey = `${currentDir()}:${currentSession}` dismissSessionAlert(sessionKey) - const [store] = globalSync.child(currentDir(), { bootstrap: false }) + const [store] = serverSync.child(currentDir(), { bootstrap: false }) const childSessions = store.session.filter((s) => s.parentID === currentSession) for (const child of childSessions) { dismissSessionAlert(`${currentDir()}:${child.id}`) @@ -535,7 +514,6 @@ export default function Layout(props: ParentProps) { }) }) - useUpdatePolling() useSDKNotificationToasts() function scrollToSession(sessionId: string, sessionKey: string) { @@ -566,11 +544,11 @@ export default function Layout(props: ParentProps) { const direct = projects.find((p) => pathKey(p.worktree) === key) if (direct) return direct - const [child] = globalSync.child(directory, { bootstrap: false }) + const [child] = serverSync.child(directory, { bootstrap: false }) const id = child.project if (!id) return - const meta = globalSync.data.project.find((p) => p.id === id) + const meta = serverSync.data.project.find((p) => p.id === id) const root = meta?.worktree if (!root) return @@ -661,7 +639,7 @@ export default function Layout(props: ParentProps) { const result: Session[] = [] for (const dir of dirs) { - const [dirStore] = globalSync.child(dir, { bootstrap: true }) + const [dirStore] = serverSync.child(dir, { bootstrap: true }) const dirSessions = sortedRootSessions(dirStore, now) result.push(...dirSessions) } @@ -713,7 +691,7 @@ export default function Layout(props: ParentProps) { createEffect(() => { route() - globalSDK.url + serverSDK.url prefetchToken.value += 1 clearSessionPrefetchInflight() @@ -760,13 +738,13 @@ export default function Layout(props: ParentProps) { } async function prefetchMessages(directory: string, sessionID: string, token: number) { - const [store, setStore] = globalSync.child(directory, { bootstrap: false }) + const [store, setStore] = serverSync.child(directory, { bootstrap: false }) return runSessionPrefetch({ directory, sessionID, task: (rev) => - retry(() => globalSDK.client.session.messages({ directory, sessionID, limit: prefetchChunk })) + retry(() => serverSDK.client.session.messages({ directory, sessionID, limit: prefetchChunk })) .then((messages) => { if (prefetchToken.value !== token) return if (!isSessionPrefetchCurrent(directory, sessionID, rev)) return @@ -786,7 +764,7 @@ export default function Layout(props: ParentProps) { if (stale.length > 0) { clearSessionPrefetch(directory, stale) for (const id of stale) { - globalSync.todo.set(id, undefined) + serverSync.todo.set(id, undefined) } } @@ -851,7 +829,7 @@ export default function Layout(props: ParentProps) { const directory = session.directory if (!directory) return - const [store] = globalSync.child(directory, { bootstrap: false }) + const [store] = serverSync.child(directory, { bootstrap: false }) const cached = untrack(() => { const info = getSessionPrefetch(directory, session.id) return shouldSkipSessionPrefetch({ @@ -956,7 +934,7 @@ export default function Layout(props: ParentProps) { if (!target) return // warm up child store to prevent flicker - globalSync.child(target.worktree) + serverSync.child(target.worktree) void openProject(target.worktree) } @@ -965,7 +943,7 @@ export default function Layout(props: ParentProps) { const target = projects[index] if (!target) return - globalSync.child(target.worktree) + serverSync.child(target.worktree) void openProject(target.worktree) } @@ -994,12 +972,12 @@ export default function Layout(props: ParentProps) { } async function archiveSession(session: Session) { - const [store, setStore] = globalSync.child(session.directory) + const [store, setStore] = serverSync.child(session.directory) const sessions = store.session ?? [] const index = sessions.findIndex((s) => s.id === session.id) const nextSession = sessions[index + 1] ?? sessions[index - 1] - await globalSDK.client.session.update({ + await serverSDK.client.session.update({ directory: session.directory, sessionID: session.id, time: { archived: Date.now() }, @@ -1049,19 +1027,6 @@ export default function Layout(props: ParentProps) { keybind: "mod+alt+arrowdown", onSelect: () => navigateProjectByOffset(1), }, - ...Array.from({ length: 9 }, (_, i) => { - const index = i - const number = index + 1 - return { - id: `project.${number}`, - category: language.t("command.category.project"), - title: `Open Project {number}`, - keybind: `mod+${number}`, - disabled: layout.projects.list().length <= index, - hidden: true, - onSelect: () => navigateToProjectIndex(index), - } - }), { id: "provider.connect", title: language.t("command.provider.connect"), @@ -1081,6 +1046,18 @@ export default function Layout(props: ParentProps) { keybind: "mod+comma", onSelect: () => openSettings(), }, + ...(platform.platform === "desktop" && platform.exportDebugLogs + ? [ + { + id: "logs.export", + title: "Export logs", + category: language.t("command.category.settings"), + onSelect: () => { + void platform.exportDebugLogs?.() + }, + }, + ] + : []), { id: "session.previous", title: language.t("command.session.previous"), @@ -1164,6 +1141,21 @@ export default function Layout(props: ParentProps) { }, ] + if (!newDesign()) + Array.from({ length: 9 }, (_, i) => { + const index = i + const number = index + 1 + commands.push({ + id: `project.${number}`, + category: language.t("command.category.project"), + title: `Open Project {number}`, + keybind: `mod+${number}`, + disabled: layout.projects.list().length <= index, + hidden: true, + onSelect: () => navigateToProjectIndex(index), + }) + }) + for (const [id] of availableThemeEntries()) { commands.push({ id: `theme.set.${id}`, @@ -1253,11 +1245,11 @@ export default function Layout(props: ParentProps) { ) if (known) return known[0] - const [child] = globalSync.child(directory, { bootstrap: false }) + const [child] = serverSync.child(directory, { bootstrap: false }) const id = child.project if (!id) return directory - const meta = globalSync.data.project.find((item) => item.id === id) + const meta = serverSync.data.project.find((item) => item.id === id) return meta?.worktree ?? directory } @@ -1305,7 +1297,7 @@ export default function Layout(props: ParentProps) { } const refreshDirs = async (target?: string) => { if (!target || target === root || canOpen(target)) return canOpen(target) - const listed = await globalSDK.client.worktree + const listed = await serverSDK.client.worktree .list({ directory: root }) .then((x) => x.data ?? []) .catch(() => [] as string[]) @@ -1314,13 +1306,13 @@ export default function Layout(props: ParentProps) { } const openSession = async (target: { directory: string; id: string }) => { if (!canOpen(target.directory)) return false - const [data] = globalSync.child(target.directory, { bootstrap: false }) + const [data] = serverSync.child(target.directory, { bootstrap: false }) if (data.session.some((item) => item.id === target.id)) { setStore("lastProjectSession", root, { directory: target.directory, id: target.id, at: Date.now() }) navigateWithSidebarReset(`/${base64Encode(target.directory)}/session/${target.id}`) return true } - const resolved = await globalSDK.client.session + const resolved = await serverSDK.client.session .get({ sessionID: target.id }) .then((x) => x.data) .catch(() => undefined) @@ -1340,7 +1332,7 @@ export default function Layout(props: ParentProps) { } const latest = latestRootSession( - dirs.map((item) => globalSync.child(item, { bootstrap: false })[0]), + dirs.map((item) => serverSync.child(item, { bootstrap: false })[0]), Date.now(), ) if (latest && (await openSession(latest))) { @@ -1351,7 +1343,7 @@ export default function Layout(props: ParentProps) { await Promise.all( dirs.map(async (item) => ({ path: { directory: item }, - session: await globalSDK.client.session + session: await serverSDK.client.session .list({ directory: item }) .then((x) => x.data ?? []) .catch(() => []), @@ -1412,11 +1404,11 @@ export default function Layout(props: ParentProps) { const name = next === getFilename(project.worktree) ? "" : next if (project.id && project.id !== "global") { - await globalSDK.client.project.update({ projectID: project.id, directory: project.worktree, name }) + await serverSDK.client.project.update({ projectID: project.id, directory: project.worktree, name }) return } - globalSync.project.meta(project.worktree, { name }) + serverSync.project.meta(project.worktree, { name }) } const renameWorkspace = (directory: string, next: string, projectId?: string, branch?: string) => { @@ -1513,7 +1505,7 @@ export default function Layout(props: ParentProps) { setBusy(directory, true) - const result = await globalSDK.client.worktree + const result = await serverSDK.client.worktree .remove({ directory: root, worktreeRemoveInput: { directory } }) .then((x) => x.data) .catch((err) => { @@ -1532,7 +1524,7 @@ export default function Layout(props: ParentProps) { clearLastProjectSession(root) } - globalSync.set( + serverSync.set( "project", produce((draft) => { const project = draft.find((item) => item.worktree === root) @@ -1571,7 +1563,7 @@ export default function Layout(props: ParentProps) { }) const dismiss = () => toaster.dismiss(progress) - const sessions: Session[] = await globalSDK.client.session + const sessions: Session[] = await serverSDK.client.session .list({ directory }) .then((x) => x.data ?? []) .catch(() => []) @@ -1582,9 +1574,9 @@ export default function Layout(props: ParentProps) { platform, getTerminalServerScope(server.current, server.key), ) - await globalSDK.client.instance.dispose({ directory }).catch(() => undefined) + await serverSDK.client.instance.dispose({ directory }).catch(() => undefined) - const result = await globalSDK.client.worktree + const result = await serverSDK.client.worktree .reset({ directory: root, worktreeResetInput: { directory } }) .then((x) => x.data) .catch((err) => { @@ -1606,7 +1598,7 @@ export default function Layout(props: ParentProps) { sessions .filter((session) => session.time.archived === undefined) .map((session) => - globalSDK.client.session + serverSDK.client.session .update({ sessionID: session.id, directory: session.directory, @@ -1647,7 +1639,7 @@ export default function Layout(props: ParentProps) { }) onMount(() => { - globalSDK.client.file + serverSDK.client.file .status({ directory: props.directory }) .then((x) => { const files = x.data ?? [] @@ -1706,7 +1698,7 @@ export default function Layout(props: ParentProps) { }) const refresh = async () => { - const sessions = await globalSDK.client.session + const sessions = await serverSDK.client.session .list({ directory: props.directory }) .then((x) => x.data ?? []) .catch(() => []) @@ -1715,7 +1707,7 @@ export default function Layout(props: ParentProps) { } onMount(() => { - globalSDK.client.file + serverSDK.client.file .status({ directory: props.directory }) .then((x) => { const files = x.data ?? [] @@ -1826,8 +1818,10 @@ export default function Layout(props: ParentProps) { ) createEffect(() => { - const sidebarWidth = layout.sidebar.opened() ? layout.sidebar.width() : 48 - document.documentElement.style.setProperty("--dialog-left-margin", `${sidebarWidth}px`) + document.documentElement.style.setProperty( + "--dialog-left-margin", + newDesign() ? "0px" : `${layout.sidebar.opened() ? layout.sidebar.width() : 48}px`, + ) }) const side = createMemo(() => Math.max(layout.sidebar.width(), 244)) @@ -1847,7 +1841,7 @@ export default function Layout(props: ParentProps) { const next = new Set(dirs) for (const directory of next) { if (loadedSessionDirs.has(directory)) continue - void globalSync.project.loadSessions(directory) + void serverSync.project.loadSessions(directory) } loadedSessionDirs.clear() @@ -1944,7 +1938,7 @@ export default function Layout(props: ParentProps) { const createWorkspace = async (project: LocalProject) => { clearSidebarHoverState() - const created = await globalSDK.client.worktree + const created = await serverSDK.client.worktree .create({ directory: project.worktree }) .then((x) => x.data) .catch((err) => { @@ -1978,7 +1972,7 @@ export default function Layout(props: ParentProps) { return [created.directory, ...next] }) - globalSync.child(created.directory) + serverSync.child(created.directory) navigateWithSidebarReset(`/${base64Encode(created.directory)}/session`) } @@ -2083,7 +2077,7 @@ export default function Layout(props: ParentProps) { if (!item) return false return item.vcs === "git" || layout.sidebar.workspaces(item.worktree)() }) - const homedir = createMemo(() => globalSync.data.path.home) + const homedir = createMemo(() => serverSync.data.path.home) return (
0 && providers.paid().length === 0), + hidden: store.gettingStartedDismissed || !(providers.all().size > 0 && providers.paid().length === 0), }} >
@@ -2369,153 +2363,212 @@ export default function Layout(props: ParentProps) { ) return ( -
- {autoselecting() ?? ""} - -
-
-
- - - - + } + > +
+ {autoselecting() ?? ""} + + + + +
+
+
+ + + + + + + + ) } + +function UpdateAvailableToast(props: { + version: string + install: () => void + language: ReturnType +}) { + let toastId: number | undefined + + onMount(() => { + toastId = showToast({ + persistent: true, + icon: "download", + title: props.language.t("toast.update.title"), + description: props.language.t("toast.update.description", { version: props.version }), + actions: [ + { + label: props.language.t("toast.update.action.installRestart"), + onClick: props.install, + }, + { + label: props.language.t("toast.update.action.notYet"), + onClick: "dismiss", + }, + ], + }) + }) + + onCleanup(() => { + if (toastId === undefined) return + toaster.dismiss(toastId) + }) + + return null +} diff --git a/packages/app/src/pages/layout/helpers.ts b/packages/app/src/pages/layout/helpers.ts index d53381e40462..1e05199a25a8 100644 --- a/packages/app/src/pages/layout/helpers.ts +++ b/packages/app/src/pages/layout/helpers.ts @@ -55,6 +55,29 @@ export const childSessionOnPath = (sessions: Session[] | undefined, rootID: stri export const displayName = (project: { name?: string; worktree: string }) => project.name || getFilename(project.worktree) +const OPENCODE_PROJECT_ID = "4b0ea68d7af9a6031a7ffda7ad66e0cb83315750" + +export function getProjectAvatarSource(id?: string, icon?: { color?: string; url?: string; override?: string }) { + if (id === OPENCODE_PROJECT_ID) return "https://opencode.ai/favicon.svg" + if (icon?.override) return icon.override + if (icon?.color) return undefined + return icon?.url +} + +export function projectForSession( + session: Session, + projects: T[], + byID: Map, +) { + const direct = byID.get(session.projectID) + if (direct) return direct + const directory = pathKey(session.directory) + return projects.find( + (project) => + pathKey(project.worktree) === directory || project.sandboxes?.some((sandbox) => pathKey(sandbox) === directory), + ) +} + export const errorMessage = (err: unknown, fallback: string) => { if (err && typeof err === "object" && "data" in err) { const data = (err as { data?: { message?: string } }).data diff --git a/packages/app/src/pages/layout/sidebar-items.tsx b/packages/app/src/pages/layout/sidebar-items.tsx index 77d9a03d9de2..dbb8d588399a 100644 --- a/packages/app/src/pages/layout/sidebar-items.tsx +++ b/packages/app/src/pages/layout/sidebar-items.tsx @@ -7,7 +7,7 @@ import { Tooltip } from "@opencode-ai/ui/tooltip" import { getFilename } from "@opencode-ai/core/util/path" import { A, useParams } from "@solidjs/router" import { type Accessor, createMemo, For, type JSX, Match, Show, Switch } from "solid-js" -import { useGlobalSync } from "@/context/global-sync" +import { useServerSync } from "@/context/server-sync" import { useLanguage } from "@/context/language" import { getAvatarColors, type LocalProject, useLayout } from "@/context/layout" import { useNotification } from "@/context/notification" @@ -15,16 +15,7 @@ import { usePermission } from "@/context/permission" import { messageAgentColor } from "@/utils/agent" import { sessionTitle } from "@/utils/session-title" import { sessionPermissionRequest } from "../session/composer/session-request-tree" -import { childSessionOnPath, hasProjectPermissions } from "./helpers" - -const OPENCODE_PROJECT_ID = "4b0ea68d7af9a6031a7ffda7ad66e0cb83315750" - -export function getProjectAvatarSource(id?: string, icon?: { color?: string; url?: string; override?: string }) { - if (id === OPENCODE_PROJECT_ID) return "https://opencode.ai/favicon.svg" - if (icon?.override) return icon?.override - if (icon?.color) return undefined - return icon?.url -} +import { childSessionOnPath, getProjectAvatarSource, hasProjectPermissions } from "./helpers" export const ProjectIcon = (props: { project: LocalProject @@ -32,7 +23,7 @@ export const ProjectIcon = (props: { notify?: boolean working?: boolean }): JSX.Element => { - const globalSync = useGlobalSync() + const serverSync = useServerSync() const notification = useNotification() const permission = usePermission() const dirs = createMemo(() => [props.project.worktree, ...(props.project.sandboxes ?? [])]) @@ -42,7 +33,7 @@ export const ProjectIcon = (props: { const hasError = createMemo(() => dirs().some((directory) => notification.project.unseenHasError(directory))) const hasPermissions = createMemo(() => dirs().some((directory) => { - const [store] = globalSync.child(directory, { bootstrap: false }) + const [store] = serverSync.child(directory, { bootstrap: false }) return hasProjectPermissions(store.permission, (item) => !permission.autoResponds(item, directory)) }), ) @@ -155,10 +146,10 @@ export const SessionItem = (props: SessionItemProps): JSX.Element => { const language = useLanguage() const notification = useNotification() const permission = usePermission() - const globalSync = useGlobalSync() + const serverSync = useServerSync() const unseenCount = createMemo(() => notification.session.unseenCount(props.session.id)) const hasError = createMemo(() => notification.session.unseenHasError(props.session.id)) - const [sessionStore] = globalSync.child(props.session.directory) + const [sessionStore] = serverSync.child(props.session.directory) const hasPermissions = createMemo(() => { return !!sessionPermissionRequest(sessionStore.session, sessionStore.permission, props.session.id, (item) => { return !permission.autoResponds(item, props.session.directory) diff --git a/packages/app/src/pages/layout/sidebar-project.tsx b/packages/app/src/pages/layout/sidebar-project.tsx index b910dd2098b7..7afaa87ff865 100644 --- a/packages/app/src/pages/layout/sidebar-project.tsx +++ b/packages/app/src/pages/layout/sidebar-project.tsx @@ -7,7 +7,7 @@ import { HoverCard } from "@opencode-ai/ui/hover-card" import { Icon } from "@opencode-ai/ui/icon" import { createSortable } from "@thisbeyond/solid-dnd" import { useLayout, type LocalProject } from "@/context/layout" -import { useGlobalSync } from "@/context/global-sync" +import { useServerSync } from "@/context/server-sync" import { useLanguage } from "@/context/language" import { useNotification } from "@/context/notification" import { ProjectIcon, SessionItem, type SessionItemProps } from "./sidebar-items" @@ -274,7 +274,7 @@ export const SortableProject = (props: { ctx: ProjectSidebarContext sortNow: Accessor }): JSX.Element => { - const globalSync = useGlobalSync() + const serverSync = useServerSync() const language = useLanguage() const sortable = createSortable(props.project.worktree) const selected = createMemo(() => props.ctx.currentProject()?.worktree === props.project.worktree) @@ -294,23 +294,23 @@ export const SortableProject = (props: { const hoverOpen = () => isHoverProject() && preview() && !selected() && !state.menu const label = (directory: string) => { - const [data] = globalSync.child(directory, { bootstrap: false }) + const [data] = serverSync.child(directory, { bootstrap: false }) const kind = directory === props.project.worktree ? language.t("workspace.type.local") : language.t("workspace.type.sandbox") const name = props.ctx.workspaceLabel(directory, data.vcs?.branch, props.project.id) return `${kind} : ${name}` } - const projectStore = createMemo(() => globalSync.child(props.project.worktree, { bootstrap: false })[0]) + const projectStore = createMemo(() => serverSync.child(props.project.worktree, { bootstrap: false })[0]) const isWorking = createMemo(() => dirs().some((directory) => { - const [store] = globalSync.child(directory, { bootstrap: false }) + const [store] = serverSync.child(directory, { bootstrap: false }) return Object.keys(store.session_status).some((id) => store.session_working(id)) }), ) const projectSessions = createMemo(() => sortedRootSessions(projectStore(), props.sortNow())) const workspaceSessions = (directory: string) => { - const [data] = globalSync.child(directory, { bootstrap: false }) + const [data] = serverSync.child(directory, { bootstrap: false }) return sortedRootSessions(data, props.sortNow()) } const tile = () => ( diff --git a/packages/app/src/pages/layout/sidebar-workspace.tsx b/packages/app/src/pages/layout/sidebar-workspace.tsx index f423c13d1e7a..a8b6ad8f8e5c 100644 --- a/packages/app/src/pages/layout/sidebar-workspace.tsx +++ b/packages/app/src/pages/layout/sidebar-workspace.tsx @@ -14,7 +14,7 @@ import { Spinner } from "@opencode-ai/ui/spinner" import { Tooltip } from "@opencode-ai/ui/tooltip" import { type Session } from "@opencode-ai/sdk/v2/client" import { type LocalProject } from "@/context/layout" -import { useGlobalSync, useQueryOptions } from "@/context/global-sync" +import { useServerSync, useQueryOptions } from "@/context/server-sync" import { useLanguage } from "@/context/language" import { pathKey } from "@/utils/path-key" import { NewSessionItem, SessionItem, SessionSkeleton } from "./sidebar-items" @@ -60,7 +60,7 @@ export const WorkspaceDragOverlay = (props: { activeWorkspace: Accessor workspaceLabel: (directory: string, branch?: string, projectId?: string) => string }): JSX.Element => { - const globalSync = useGlobalSync() + const serverSync = useServerSync() const language = useLanguage() const label = createMemo(() => { const project = props.sidebarProject() @@ -68,7 +68,7 @@ export const WorkspaceDragOverlay = (props: { const directory = props.activeWorkspace() if (!directory) return - const [workspaceStore] = globalSync.child(directory, { bootstrap: false }) + const [workspaceStore] = serverSync.child(directory, { bootstrap: false }) const kind = directory === project.worktree ? language.t("workspace.type.local") : language.t("workspace.type.sandbox") const name = props.workspaceLabel(directory, workspaceStore.vcs?.branch, project.id) @@ -299,11 +299,11 @@ export const SortableWorkspace = (props: { }): JSX.Element => { const navigate = useNavigate() const params = useParams() - const globalSync = useGlobalSync() + const serverSync = useServerSync() const queryOptions = useQueryOptions() const language = useLanguage() const sortable = createSortable(props.directory) - const [workspaceStore, setWorkspaceStore] = globalSync.child(props.directory, { bootstrap: false }) + const [workspaceStore, setWorkspaceStore] = serverSync.child(props.directory, { bootstrap: false }) const [menu, setMenu] = createStore({ open: false, pendingRename: false, @@ -328,7 +328,7 @@ export const SortableWorkspace = (props: { const showNew = createMemo(() => !loading() && (touch() || count() === 0 || (active() && !params.id))) const loadMore = async () => { setWorkspaceStore("limit", (limit) => (limit ?? 0) + 5) - await globalSync.project.loadSessions(props.directory) + await serverSync.project.loadSessions(props.directory) } const workspaceEditActive = createMemo(() => props.ctx.editorOpen(`workspace:${props.directory}`)) @@ -357,7 +357,7 @@ export const SortableWorkspace = (props: { createEffect(() => { if (!boot()) return - globalSync.child(props.directory, { bootstrap: true }) + serverSync.child(props.directory, { bootstrap: true }) }) return ( @@ -446,11 +446,11 @@ export const LocalWorkspace = (props: { sortNow: Accessor mobile?: boolean }): JSX.Element => { - const globalSync = useGlobalSync() + const serverSync = useServerSync() const queryOptions = useQueryOptions() const language = useLanguage() const workspace = createMemo(() => { - const [store, setStore] = globalSync.child(props.project.worktree) + const [store, setStore] = serverSync.child(props.project.worktree) return { store, setStore } }) const slug = createMemo(() => base64Encode(props.project.worktree)) @@ -461,7 +461,7 @@ export const LocalWorkspace = (props: { const loading = () => fetching() > 0 && count() === 0 const loadMore = async () => { workspace().setStore("limit", (limit) => (limit ?? 0) + 5) - await globalSync.project.loadSessions(props.project.worktree) + await serverSync.project.loadSessions(props.project.worktree) } return ( diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 5e93ff5bca43..312b5c3a4d8e 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -18,6 +18,7 @@ import { import { makeEventListener } from "@solid-primitives/event-listener" import { createMediaQuery } from "@solid-primitives/media" import { createResizeObserver } from "@solid-primitives/resize-observer" +import { debounce } from "@solid-primitives/scheduled" import { useLocal } from "@/context/local" import { selectionFromLines, useFile, type FileSelection, type SelectedLineRange } from "@/context/file" import { createStore } from "solid-js/store" @@ -30,10 +31,10 @@ import { Button } from "@opencode-ai/ui/button" import { showToast } from "@opencode-ai/ui/toast" import { checksum } from "@opencode-ai/core/util/encode" import { useLocation, useSearchParams } from "@solidjs/router" -import { NewSessionView, SessionHeader } from "@/components/session" +import { NewSessionDesignView, NewSessionView, SessionHeader } from "@/components/session" import { useComments } from "@/context/comments" import { getSessionPrefetch, SESSION_PREFETCH_TTL } from "@/context/global-sync/session-prefetch" -import { useGlobalSync } from "@/context/global-sync" +import { useServerSync } from "@/context/server-sync" import { useLanguage } from "@/context/language" import { useLayout } from "@/context/layout" import { usePrompt } from "@/context/prompt" @@ -58,6 +59,7 @@ import { SessionSidePanel } from "@/pages/session/session-side-panel" import { TerminalPanel } from "@/pages/session/terminal-panel" import { useSessionCommands } from "@/pages/session/use-session-commands" import { useSessionHashScroll } from "@/pages/session/use-session-hash-scroll" +import { shouldUseV2NewSessionPage } from "@/pages/session/new-session-layout" import { Identifier } from "@/utils/id" import { diffs as list } from "@/utils/diffs" import { Persist, persisted } from "@/utils/persist" @@ -179,7 +181,7 @@ function createSessionHistoryLoader(input: SessionHistoryWindowInput) { } export default function Page() { - const globalSync = useGlobalSync() + const serverSync = useServerSync() const layout = useLayout() const local = useLocal() const file = useFile() @@ -195,6 +197,7 @@ export default function Page() { const [searchParams, setSearchParams] = useSearchParams<{ prompt?: string }>() const location = useLocation() const { params, sessionKey, tabs, view } = useSessionLayout() + const newSessionDesign = createMemo(() => settings.general.newLayoutDesigns()) createEffect(() => { if (!prompt.ready()) return @@ -261,8 +264,10 @@ export default function Page() { const isDesktop = createMediaQuery("(min-width: 768px)") const size = createSizing() - const desktopReviewOpen = createMemo(() => isDesktop() && view().reviewPanel.opened()) - const desktopFileTreeOpen = createMemo(() => isDesktop() && layout.fileTree.opened()) + const isV2NewSessionPage = () => + shouldUseV2NewSessionPage({ newLayoutDesigns: newSessionDesign(), sessionID: params.id }) + const desktopReviewOpen = createMemo(() => isDesktop() && view().reviewPanel.opened() && !isV2NewSessionPage()) + const desktopFileTreeOpen = createMemo(() => isDesktop() && layout.fileTree.opened() && !isV2NewSessionPage()) const desktopSidePanelOpen = createMemo(() => desktopReviewOpen() || desktopFileTreeOpen()) const sessionPanelWidth = createMemo(() => { if (!desktopSidePanelOpen()) return "100%" @@ -476,7 +481,7 @@ export default function Page() { : skipToken, } }) - const refreshVcs = () => void queryClient.invalidateQueries({ queryKey: vcsKey() }) + const refreshVcs = debounce(() => void queryClient.invalidateQueries({ queryKey: vcsKey() }), 100) const reviewDiffs = () => { if (store.changes === "git" || store.changes === "branch") // avoids suspense @@ -555,11 +560,11 @@ export default function Page() { } function upsert(next: Project) { - const list = globalSync.data.project + const list = serverSync.data.project sync.set("project", next.id) const idx = list.findIndex((item) => item.id === next.id) if (idx >= 0) { - globalSync.set( + serverSync.set( "project", list.map((item, i) => (i === idx ? { ...item, ...next } : item)), ) @@ -567,10 +572,10 @@ export default function Page() { } const at = list.findIndex((item) => item.id > next.id) if (at >= 0) { - globalSync.set("project", [...list.slice(0, at), next, ...list.slice(at)]) + serverSync.set("project", [...list.slice(0, at), next, ...list.slice(at)]) return } - globalSync.set("project", [...list, next]) + serverSync.set("project", [...list, next]) } const gitMutation = useMutation(() => ({ @@ -668,7 +673,7 @@ export default function Page() { todoTimer = undefined if (!id) return if (status === "idle" && !blocked) return - const cached = untrack(() => sync.data.todo[id] !== undefined || globalSync.data.session_todo[id] !== undefined) + const cached = untrack(() => sync.data.todo[id] !== undefined || serverSync.data.session_todo[id] !== undefined) todoFrame = requestAnimationFrame(() => { todoFrame = undefined @@ -1381,7 +1386,7 @@ export default function Page() { const ok = await sendFollowupDraft({ client: sdk.client, sync, - globalSync, + serverSync, draft: item, optimisticBusy: item.sessionDirectory === sdk.directory, }).catch((err) => { @@ -1648,6 +1653,59 @@ export default function Page() { useUsageExceededDialogs() + const composerRegion = (placement: "dock" | "inline") => ( + { + inputRef = el + }} + newSessionWorktree={newSessionWorktree()} + onNewSessionWorktreeReset={() => setStore("newSessionWorktree", "main")} + onSubmit={() => { + comments.clear() + resumeScroll() + }} + onResponseSubmit={resumeScroll} + followup={ + params.id && !isChildSession() + ? { + queue: queueEnabled, + items: followupDock(), + sending: sendingFollowup(), + edit: editingFollowup(), + onQueue: queueFollowup, + onAbort: () => { + const id = params.id + if (!id) return + setFollowup("paused", id, true) + }, + onSend: (id) => { + void sendFollowup(params.id!, id, { manual: true }) + }, + onEdit: editFollowup, + onEditLoaded: clearFollowupEdit, + } + : undefined + } + revert={ + rolled().length > 0 + ? { + items: rolled(), + restoring: restoring(), + disabled: reverting(), + onRestore: restore, + } + : undefined + } + setPromptDockRef={(el) => { + promptDock = el + }} + /> + ) + return (
{sessionSync() ?? ""} @@ -1678,12 +1736,12 @@ export default function Page() { - {/* Session panel */}
- + }> + {composerRegion("inline")} +
- { - inputRef = el - }} - newSessionWorktree={newSessionWorktree()} - onNewSessionWorktreeReset={() => setStore("newSessionWorktree", "main")} - onSubmit={() => { - comments.clear() - resumeScroll() - }} - onResponseSubmit={resumeScroll} - followup={ - params.id && !isChildSession() - ? { - queue: queueEnabled, - items: followupDock(), - sending: sendingFollowup(), - edit: editingFollowup(), - onQueue: queueFollowup, - onAbort: () => { - const id = params.id - if (!id) return - setFollowup("paused", id, true) - }, - onSend: (id) => { - void sendFollowup(params.id!, id, { manual: true }) - }, - onEdit: editFollowup, - onEditLoaded: clearFollowupEdit, - } - : undefined - } - revert={ - rolled().length > 0 - ? { - items: rolled(), - restoring: restoring(), - disabled: reverting(), - onRestore: restore, - } - : undefined - } - setPromptDockRef={(el) => { - promptDock = el - }} - /> + {composerRegion("dock")}
size.start()}> diff --git a/packages/app/src/pages/session/composer/session-composer-region.tsx b/packages/app/src/pages/session/composer/session-composer-region.tsx index e6bfd05ec405..6f731234c410 100644 --- a/packages/app/src/pages/session/composer/session-composer-region.tsx +++ b/packages/app/src/pages/session/composer/session-composer-region.tsx @@ -22,6 +22,7 @@ export function SessionComposerRegion(props: { state: SessionComposerState ready: boolean centered: boolean + placement?: "dock" | "inline" inputRef: (el: HTMLDivElement) => void newSessionWorktree: string onNewSessionWorktreeReset: () => void @@ -142,11 +143,15 @@ export function SessionComposerRegion(props: {
@@ -256,6 +261,7 @@ export function SessionComposerRegion(props: { fallback={ const params = useParams() const sdk = useSDK() const sync = useSync() - const globalSync = useGlobalSync() + const serverSync = useServerSync() const language = useLanguage() const permission = usePermission() @@ -50,7 +50,7 @@ export function createSessionComposerState(options?: { closeMs?: number | (() => const todos = createMemo((): Todo[] => { const id = params.id if (!id) return [] - return globalSync.data.session_todo[id] ?? [] + return serverSync.data.session_todo[id] ?? [] }) const done = createMemo( @@ -111,7 +111,7 @@ export function createSessionComposerState(options?: { closeMs?: number | (() => const clear = () => { const id = params.id if (!id) return - globalSync.todo.set(id, []) + serverSync.todo.set(id, []) sync.set("todo", id, []) } diff --git a/packages/app/src/pages/session/message-timeline.data.ts b/packages/app/src/pages/session/message-timeline.data.ts index c6294d3e38d8..0643a424ea19 100644 --- a/packages/app/src/pages/session/message-timeline.data.ts +++ b/packages/app/src/pages/session/message-timeline.data.ts @@ -23,7 +23,6 @@ export type TimelineRowMap = { userMessageID: string group: PartGroup previousAssistantPart: boolean - lastAssistantPart: boolean } Thinking: { userMessageID: string; reasoningHeading?: string } Retry: { userMessageID: string } @@ -50,7 +49,6 @@ export namespace TimelineRow { userMessageID: string group: PartGroup previousAssistantPart: boolean - lastAssistantPart: boolean }> {} export class Thinking extends Data.TaggedClass("Thinking")<{ userMessageID: string @@ -151,8 +149,6 @@ export namespace Timeline { ), ] : groupParts(assistantPartRefs).map((group) => ({ type: "part" as const, group })) - const assistantGroupCount = assistantItems.filter((item) => item.type === "part").length - if (comments.length > 0) rows.push( new TimelineRow.CommentStrip({ @@ -195,7 +191,6 @@ export namespace Timeline { userMessageID: userMessage.id, group: item.group, previousAssistantPart: assistantGroupIndex > 0, - lastAssistantPart: assistantGroupIndex === assistantGroupCount - 1, }), ) assistantGroupIndex += 1 diff --git a/packages/app/src/pages/session/message-timeline.tsx b/packages/app/src/pages/session/message-timeline.tsx index 1df861cfc383..e071597c8ab1 100644 --- a/packages/app/src/pages/session/message-timeline.tsx +++ b/packages/app/src/pages/session/message-timeline.tsx @@ -1,4 +1,16 @@ -import { createEffect, createMemo, createSignal, For, Index, on, onCleanup, Show, mapArray, type JSX } from "solid-js" +import { + createEffect, + createMemo, + createSignal, + For, + Index, + on, + onCleanup, + Show, + mapArray, + type Accessor, + type JSX, +} from "solid-js" import { createStore, produce } from "solid-js/store" import { Dynamic } from "solid-js/web" import { useNavigate } from "@solidjs/router" @@ -48,11 +60,12 @@ import { useDialog } from "@opencode-ai/ui/context/dialog" import { createResizeObserver } from "@solid-primitives/resize-observer" import { useLanguage } from "@/context/language" import { useSessionKey } from "@/pages/session/session-layout" -import { useGlobalSDK } from "@/context/global-sdk" +import { useServerSDK } from "@/context/server-sdk" import { usePlatform } from "@/context/platform" import { useSettings } from "@/context/settings" import { useSDK } from "@/context/sdk" import { useSync } from "@/context/sync" +import { notifySessionTabsRemoved } from "@/components/titlebar-session-events" import { messageAgentColor } from "@/utils/agent" import { sessionTitle } from "@/utils/session-title" import { makeTimer } from "@solid-primitives/timer" @@ -245,7 +258,7 @@ function TimelineDiffView(props: { diff: SummaryDiff }) { return (
- +
) } @@ -273,7 +286,7 @@ export function MessageTimeline(props: { let touchGesture: number | undefined const navigate = useNavigate() - const globalSDK = useGlobalSDK() + const serverSDK = useServerSDK() const sdk = useSDK() const sync = useSync() const settings = useSettings() @@ -415,8 +428,7 @@ export function MessageTimeline(props: { if (rows.length === 0) return rows return reuseTimelineRows(previous, [...rows, new TimelineRow.BottomSpacer()]) }) - const timelineRowByKey = createMemo(() => new Map(timelineRows().map((row) => [TimelineRow.key(row), row] as const))) - const timelineRowKeys = createMemo(() => [...timelineRowByKey().keys()], [] as string[], { equals: sameKeys }) + const timelineRowKeys = createMemo(() => timelineRows().map(TimelineRow.key), [] as string[], { equals: sameKeys }) const virtualCache = createMemo(() => readTimelineCache(sessionKey(), timelineRowKeys())) const messageRowIndex = createMemo(() => { const result = new Map() @@ -427,6 +439,14 @@ export function MessageTimeline(props: { }) return result }) + const lastAssistantGroupKey = createMemo(() => { + const result = new Map() + timelineRows().forEach((row) => { + if (row._tag !== "AssistantPart") return + result.set(row.userMessageID, row.group.key) + }) + return result + }) const keepMounted = createMemo(() => { const id = activeMessageID() if (!id) return @@ -540,6 +560,7 @@ export function MessageTimeline(props: { const [bar, setBar] = createStore({ ms: pace(640), }) + const [toolOpen, setToolOpen] = createStore>({}) let more: HTMLButtonElement | undefined let head: HTMLDivElement | undefined @@ -560,6 +581,11 @@ export function MessageTimeline(props: { const isMeasuredBottom = (root: HTMLDivElement) => root.scrollHeight - root.clientHeight - root.scrollTop <= 4 + const measureTimeline = () => { + virtualizer?.measure() + anchorMeasuredBottom() + } + function anchorMeasuredBottom() { if (!listRoot) return false if (!measuredBottomAnchored) return false @@ -704,14 +730,14 @@ export function MessageTimeline(props: { } const shareMutation = useMutation(() => ({ - mutationFn: (id: string) => globalSDK.client.session.share({ sessionID: id, directory: sdk.directory }), + mutationFn: (id: string) => serverSDK.client.session.share({ sessionID: id, directory: sdk.directory }), onError: (err) => { console.error("Failed to share session", err) }, })) const unshareMutation = useMutation(() => ({ - mutationFn: (id: string) => globalSDK.client.session.unshare({ sessionID: id, directory: sdk.directory }), + mutationFn: (id: string) => serverSDK.client.session.unshare({ sessionID: id, directory: sdk.directory }), onError: (err) => { console.error("Failed to unshare session", err) }, @@ -836,7 +862,9 @@ export function MessageTimeline(props: { if (index !== -1) draft.session.splice(index, 1) }), ) + sync.session.evict(sessionID) navigateAfterSessionRemoval(sessionID, session.parentID, nextSession?.id) + notifySessionTabsRemoved({ directory: sdk.directory, sessionIDs: [sessionID] }) }) .catch((err) => { showToast({ @@ -867,42 +895,46 @@ export function MessageTimeline(props: { if (!result) return false - sync.set( - produce((draft) => { - const removed = new Set([sessionID]) - - const byParent = new Map() - for (const item of draft.session) { - const parentID = item.parentID - if (!parentID) continue - const existing = byParent.get(parentID) - if (existing) { - existing.push(item.id) - continue - } - byParent.set(parentID, [item.id]) - } + const removed = new Set([sessionID]) + const byParent = new Map() + for (const item of sync.data.session) { + const parentID = item.parentID + if (!parentID) continue + const existing = byParent.get(parentID) + if (existing) { + existing.push(item.id) + continue + } + byParent.set(parentID, [item.id]) + } - const stack = [sessionID] - while (stack.length) { - const parentID = stack.pop() - if (!parentID) continue + const stack = [sessionID] + while (stack.length) { + const parentID = stack.pop() + if (!parentID) continue - const children = byParent.get(parentID) - if (!children) continue + const children = byParent.get(parentID) + if (!children) continue - for (const child of children) { - if (removed.has(child)) continue - removed.add(child) - stack.push(child) - } - } + for (const child of children) { + if (removed.has(child)) continue + removed.add(child) + stack.push(child) + } + } + navigateAfterSessionRemoval(sessionID, session.parentID, nextSession?.id) + + sync.set( + produce((draft) => { draft.session = draft.session.filter((s) => !removed.has(s.id)) }), ) - navigateAfterSessionRemoval(sessionID, session.parentID, nextSession?.id) + for (const id of removed) { + sync.session.evict(id) + } + notifySessionTabsRemoved({ directory: sdk.directory, sessionIDs: [...removed] }) return true } @@ -980,29 +1012,42 @@ export function MessageTimeline(props: { const getMsgPart = (messageID: string, partID: string) => getMsgParts(messageID).find((part) => part.id === partID) - const renderAssistantPartGroup = (row: TimelineRowMap["AssistantPart"]) => { - if (row.group.type === "context") { + const renderAssistantPartGroup = (row: Accessor) => { + if (row().group.type === "context") { const parts = createMemo(() => { - const group = row.group + const group = row().group if (group.type !== "context") return emptyTools return group.refs .map((ref) => getMsgPart(ref.messageID, ref.partID)) .filter((part): part is ToolPart => part?.type === "tool") }) - return + return ( + + ) } const message = createMemo(() => { - const group = row.group + const group = row().group if (group.type !== "part") return return messageByID().get(group.ref.messageID) }) const part = createMemo(() => { - const group = row.group + const group = row().group if (group.type !== "part") return return getMsgPart(group.ref.messageID, group.ref.partID) }) + const defaultOpen = createMemo(() => { + const item = part() + if (!item) return + return partDefaultOpen(item, settings.general.shellToolPartsExpanded(), settings.general.editToolPartsExpanded()) + }) return ( @@ -1012,14 +1057,13 @@ export function MessageTimeline(props: { setToolOpen(part().id, open)} deferToolContent={false} + virtualizeDiff={false} /> )} @@ -1028,25 +1072,25 @@ export function MessageTimeline(props: { ) } - function TimelineRowFrame(input: { row: FramedTimelineRow; children: JSX.Element }) { + function TimelineRowFrame(input: { row: Accessor; children: JSX.Element }) { const anchor = () => { - const row = input.row + const row = input.row() return row._tag === "CommentStrip" || (row._tag === "UserMessage" && row.anchor) } const previousUserMessage = () => { - const row = input.row + const row = input.row() return (row._tag === "CommentStrip" || row._tag === "UserMessage") && row.previousUserMessage } const previousAssistantPart = () => { - const row = input.row + const row = input.row() return row._tag === "AssistantPart" && row.previousAssistantPart } return (
{ - switch (row._tag) { + const renderTimelineRow = (row: Accessor) => { + switch (row()._tag) { case "CommentStrip": { + const commentStripRow = row as Accessor> const comments = createMemo(() => - getMsgParts(row.userMessageID).flatMap((part) => MessageComment.fromPart(part) ?? []), + getMsgParts(commentStripRow().userMessageID).flatMap((part) => MessageComment.fromPart(part) ?? []), ) return ( - +
@@ -1102,17 +1147,22 @@ export function MessageTimeline(props: { ) } case "UserMessage": { + const userMessageRow = row as Accessor> const message = createMemo(() => { - const m = messageByID().get(row.userMessageID) + const m = messageByID().get(userMessageRow().userMessageID) if (m?.role === "user") return m }) return ( - + {(message) => (
- +
)} @@ -1121,13 +1171,14 @@ export function MessageTimeline(props: { ) } case "TurnDivider": { + const turnDividerRow = row as Accessor> return ( - +
@@ -1136,22 +1187,27 @@ export function MessageTimeline(props: { ) } case "AssistantPart": { + const assistantPartRow = row as Accessor> return ( - +
-
- {renderAssistantPartGroup(row)} +
+ {renderAssistantPartGroup(assistantPartRow)}
) } case "Thinking": { + const thinkingRow = row as Accessor> return ( - +
@@ -1159,29 +1215,32 @@ export function MessageTimeline(props: { ) } case "Retry": { + const retryRow = row as Accessor> return ( - +
- +
) } case "DiffSummary": { + const diffSummaryRow = row as Accessor> return ( - +
- +
) } case "Error": { + const errorRow = row as Accessor> return ( - +
- {row.text} + {errorRow().text}
@@ -1192,12 +1251,8 @@ export function MessageTimeline(props: { } } - function TimelineRowView(props: { rowKey: string }) { - return ( - - {(item) => renderTimelineRow(item)} - - ) + function TimelineRowView(props: { row: TimelineRow.TimelineRow }) { + return renderTimelineRow(() => props.row) } return ( @@ -1236,7 +1291,6 @@ export function MessageTimeline(props: { onClick={props.onAutoScrollInteraction} class="relative min-w-0 w-full h-full" style={{ - "--session-title-height": showHeader() ? "40px" : "0px", "--sticky-accordion-top": showHeader() ? "48px" : "0px", }} > @@ -1256,16 +1310,14 @@ export function MessageTimeline(props: { }} > -