diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000000..3e16c33d41 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,9 @@ +{ + "permissions": { + "allow": [ + "Bash(rm:*)" + ], + "deny": [], + "ask": [] + } +} diff --git a/.gitignore b/.gitignore index b545240576..3318e3af3a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ playground tmp dist .turbo +/packages/app/release +/packages/app +/packages/desktop/src-tauri/gen/apple/build diff --git a/AGENTS.md b/AGENTS.md index 36a37713bd..d0107960e4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,47 +1,175 @@ -## IMPORTANT +# AGENTS.md -- Try to keep things in one function unless composable or reusable -- DO NOT do unnecessary destructuring of variables -- DO NOT use `else` statements unless necessary -- DO NOT use `try`/`catch` if it can be avoided -- AVOID `try`/`catch` where possible -- AVOID `else` statements -- AVOID using `any` type -- AVOID `let` statements -- PREFER single word variable names where possible -- Use as many bun apis as possible like Bun.file() +## Development Commands -## Debugging +### Build & Development -- To test opencode in the `packages/opencode` directory you can run `bun dev` +- `bun dev` - Start development server for opencode package +- `bun run build` - Build the entire project +- `bun run build:dev` - Build for development +- `bun run test` - Run all tests +- `bun run typecheck` - Type checking +- `bun run lint` - Lint code +- `bun run format` - Check formatting +- `bun run format:fix` - Fix formatting issues -## Tool Calling +### Testing -- ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE. Here is an example illustrating how to execute 3 parallel file reads in this chat environnement: +- `bun test` - Run all tests +- `npx vitest run tests/file-name.test.ts` - Run specific test file -json +## Project Structure + +This is a monorepo with the following structure: + +### Core Packages + +- `packages/opencode/` - Main opencode CLI tool +- `packages/console/` - Web console interface +- `packages/core/` - Core functionality +- `packages/function/` - Serverless functions +- `packages/mail/` - Email templates and functionality +- `packages/resource/` - Shared resources +- `packages/scripts/` - Build and utility scripts + +### SDKs + +- `packages/sdk/go/` - Go SDK +- `packages/sdk/js/` - JavaScript SDK + +### Applications + +- `packages/desktop/` - Desktop application (Tauri-based) +- `packages/web/` - Web application (Astro-based) +- `packages/tui/` - Terminal user interface (Go-based) + +### Extensions + +- `packages/plugin/` - Plugin system +- `packages/vscode/` - VS Code extension + +## Code Style Guidelines + +### Core Principles + +- **Single Function**: Keep things in one function unless composable or reusable +- **No Destructuring**: Avoid unnecessary destructuring of variables +- **No Else**: Avoid `else` statements unless absolutely necessary +- **No Try/Catch**: Avoid `try`/`catch` where possible +- **No Any**: Avoid using `any` type +- **No Let**: Prefer `const` over `let` +- **Single Words**: Prefer single word variable names where possible +- **Bun APIs**: Use as many bun apis as possible like Bun.file() + +### TypeScript Standards + +- **Strict typing**: Use explicit function return types +- **Organized imports**: Group by type (external, internal, relative) +- **Naming conventions**: PascalCase for types/components, camelCase for variables/functions +- **Error handling**: Explicit error types, avoid `any` suppression + +## Development Guidelines + +### When Adding New Features + +1. Use existing patterns and conventions +2. Follow the established file structure +3. Add appropriate tests +4. Run linting and type checking +5. Update documentation if needed + +### File Organization + +- Keep related files together +- Use index.ts for exports when appropriate +- Follow existing directory naming conventions +- Use descriptive file names that indicate purpose + +### Testing + +- Use vitest for testing +- Mock external dependencies with vi.mock/vi.spyOn +- Test both success and error cases +- Keep tests focused and isolated + +## Environment Setup + +1. Install dependencies: `bun install` +2. Copy environment variables if needed +3. Run development server: `bun dev` +4. Run tests: `bun test` + +## Common Tasks + +### Adding a New Package + +1. Create directory in appropriate location +2. Add package.json with proper dependencies +3. Add to workspace configuration +4. Follow existing patterns for structure + +### Adding a New Component + +1. Check existing components for patterns +2. Use TypeScript with proper typing +3. Add to appropriate index file for exports +4. Add tests if component has business logic + +### Debugging + +- Use console.log with component prefixes for debugging +- Check browser console for errors +- Use development mode for better error messages +- Run tests to verify functionality + +## Tool Calling Best Practices + +### Parallel Tool Usage + +Always use parallel tools when applicable. Example: + +```json { - "recipient_name": "multi_tool_use.parallel", - "parameters": { - "tool_uses": [ - { - "recipient_name": "functions.read", - "parameters": { - "filePath": "path/to/file.tsx" - } - }, - { - "recipient_name": "functions.read", - "parameters": { - "filePath": "path/to/file.ts" - } - }, - { - "recipient_name": "functions.read", - "parameters": { - "filePath": "path/to/file.md" - } - } - ] - } + "recipient_name": "multi_tool_use.parallel", + "parameters": { + "tool_uses": [ + { + "recipient_name": "functions.read", + "parameters": { + "filePath": "path/to/file.tsx" + } + }, + { + "recipient_name": "functions.read", + "parameters": { + "filePath": "path/to/file.ts" + } + }, + { + "recipient_name": "functions.read", + "parameters": { + "filePath": "path/to/file.md" + } + } + ] + } } +``` + +## Build System + +The project uses: + +- **Bun** as package manager and runtime +- **Turbo** for monorepo builds +- **Vite** for bundling +- **TypeScript** for type checking +- **ESLint** for linting +- **Prettier** for formatting + +## Deployment + +- GitHub Actions for CI/CD +- Automatic deployment on merge to main +- Staging deployments for feature branches +- Build artifacts are generated in dist/ directories diff --git a/STATS.md b/STATS.md index de0ca37f75..775c4200ad 100644 --- a/STATS.md +++ b/STATS.md @@ -103,10 +103,10 @@ | 2025-10-06 | 460,927 (+5,368) | 379,489 (+4,744) | 840,416 (+10,112) | | 2025-10-07 | 467,336 (+6,409) | 385,438 (+5,949) | 852,774 (+12,358) | | 2025-10-08 | 474,643 (+7,307) | 394,139 (+8,701) | 868,782 (+16,008) | -| 2025-10-09 | 479,203 (+4,560) | 400,526 (+6,387) | 879,729 (+10,947) | -| 2025-10-10 | 484,374 (+5,171) | 406,015 (+5,489) | 890,389 (+10,660) | -| 2025-10-11 | 488,427 (+4,053) | 414,699 (+8,684) | 903,126 (+12,737) | -| 2025-10-12 | 492,125 (+3,698) | 418,745 (+4,046) | 910,870 (+7,744) | -| 2025-10-14 | 505,130 (+13,005) | 429,286 (+10,541) | 934,416 (+23,546) | -| 2025-10-15 | 512,717 (+7,587) | 439,290 (+10,004) | 952,007 (+17,591) | -| 2025-10-16 | 517,719 (+5,002) | 447,137 (+7,847) | 964,856 (+12,849) | +| 2025-10-11 | 488,430 (+13,787) | 414,699 (+20,560) | 903,129 (+34,347) | +| 2025-10-12 | 492,126 (+3,696) | 418,745 (+4,046) | 910,871 (+7,742) | +| 2025-10-13 | 497,573 (+5,447) | 423,531 (+4,786) | 921,104 (+10,233) | +| 2025-10-14 | 505,190 (+7,617) | 429,286 (+5,755) | 934,476 (+13,372) | +| 2025-10-15 | 512,767 (+7,577) | 439,290 (+10,004) | 952,057 (+17,581) | +| 2025-10-16 | 517,739 (+4,972) | 447,137 (+7,847) | 964,876 (+12,819) | +| 2025-10-17 | 526,294 (+8,555) | 457,467 (+10,330) | 983,761 (+18,885) | diff --git a/bun.lock b/bun.lock index 8da8c5ce30..479a5f4e5f 100644 --- a/bun.lock +++ b/bun.lock @@ -122,18 +122,17 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "0.15.4", + "version": "0.14.7", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", - "@opencode-ai/ui": "workspace:*", "@shikijs/transformers": "3.9.2", "@solid-primitives/event-bus": "1.1.2", "@solid-primitives/resize-observer": "2.1.3", "@solid-primitives/scroll": "2.1.3", "@solidjs/router": "0.15.3", "@thisbeyond/solid-dnd": "0.7.5", - "diff": "catalog:", + "diff": "8.0.2", "fuzzysort": "catalog:", "luxon": "catalog:", "marked": "16.2.0", @@ -142,19 +141,21 @@ "shiki": "3.9.2", "solid-js": "catalog:", "solid-list": "0.3.0", - "tailwindcss": "catalog:", + "tailwindcss": "4.1.11", "virtua": "0.42.3", }, "devDependencies": { - "@tailwindcss/vite": "catalog:", + "@tailwindcss/vite": "4.1.11", + "@tauri-apps/api": "2.8.0", + "@tauri-apps/cli": "2.8.4", "@tsconfig/bun": "1.0.9", "@types/luxon": "3.7.1", "@types/node": "catalog:", - "@typescript/native-preview": "catalog:", + "concurrently": "^9.1.2", "typescript": "catalog:", - "vite": "catalog:", + "vite": "^6.0.0", "vite-plugin-icons-spritesheet": "3.0.1", - "vite-plugin-solid": "catalog:", + "vite-plugin-solid": "^2.11.6", }, }, "packages/function": { @@ -1080,13 +1081,13 @@ "@rollup/plugin-alias": ["@rollup/plugin-alias@5.1.1", "", { "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ=="], - "@rollup/plugin-commonjs": ["@rollup/plugin-commonjs@28.0.7", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", "fdir": "^6.2.0", "is-reference": "1.2.1", "magic-string": "^0.30.3", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-6cE2Wr/MkpdtTS8gXlCn9Zdmf7e9Xm96yFqOwFEXuvYLAHtjRf57/n6GEVF4K8NSesT1eKdBtcDA/SQdpW/8nA=="], + "@rollup/plugin-commonjs": ["@rollup/plugin-commonjs@28.0.6", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", "fdir": "^6.2.0", "is-reference": "1.2.1", "magic-string": "^0.30.3", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-XSQB1K7FUU5QP+3lOQmVCE3I0FcbbNvmNT4VJSj93iUjayaARrTQeoRdiYQoftAJBLrR9t2agwAd3ekaTgHNlw=="], "@rollup/plugin-inject": ["@rollup/plugin-inject@5.0.5", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "estree-walker": "^2.0.2", "magic-string": "^0.30.3" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg=="], "@rollup/plugin-json": ["@rollup/plugin-json@6.1.0", "", { "dependencies": { "@rollup/pluginutils": "^5.1.0" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA=="], - "@rollup/plugin-node-resolve": ["@rollup/plugin-node-resolve@16.0.3", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", "is-module": "^1.0.0", "resolve": "^1.22.1" }, "peerDependencies": { "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg=="], + "@rollup/plugin-node-resolve": ["@rollup/plugin-node-resolve@16.0.2", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", "is-module": "^1.0.0", "resolve": "^1.22.1" }, "peerDependencies": { "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-tCtHJ2BlhSoK4cCs25NMXfV7EALKr0jyasmqVCq3y9cBrKdmJhtsy1iTz36Xhk/O+pDJbzawxF4K6ZblqCnITQ=="], "@rollup/plugin-replace": ["@rollup/plugin-replace@6.0.2", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "magic-string": "^0.30.3" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-7QaYCf8bqF04dOy7w/eHmJeNExxTYwvKAmlSAH/EaWWUzbT0h5sbF6bktFoX/0F/0qwng5/dWFMyf3gzaM8DsQ=="], @@ -1172,57 +1173,57 @@ "@slack/web-api": ["@slack/web-api@6.13.0", "", { "dependencies": { "@slack/logger": "^3.0.0", "@slack/types": "^2.11.0", "@types/is-stream": "^1.1.0", "@types/node": ">=12.0.0", "axios": "^1.7.4", "eventemitter3": "^3.1.0", "form-data": "^2.5.0", "is-electron": "2.2.2", "is-stream": "^1.1.0", "p-queue": "^6.6.1", "p-retry": "^4.0.0" } }, "sha512-dv65crIgdh9ZYHrevLU6XFHTQwTyDmNqEqzuIrV+Vqe/vgiG6w37oex5ePDU1RGm2IJ90H8iOvHFvzdEO/vB+g=="], - "@smithy/abort-controller": ["@smithy/abort-controller@4.2.2", "", { "dependencies": { "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-fPbcmEI+A6QiGOuumTpKSo7z+9VYr5DLN8d5/8jDJOwmt4HAKy/UGuRstCMpKbtr+FMaHH4pvFinSAbIAYCHZQ=="], + "@smithy/abort-controller": ["@smithy/abort-controller@4.2.0", "", { "dependencies": { "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-PLUYa+SUKOEZtXFURBu/CNxlsxfaFGxSBPcStL13KpVeVWIfdezWyDqkz7iDLmwnxojXD0s5KzuB5HGHvt4Aeg=="], - "@smithy/config-resolver": ["@smithy/config-resolver@4.3.2", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.2", "@smithy/types": "^4.7.1", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-middleware": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-F/G+VaulIebINyfvcoXmODgIc7JU/lxWK9/iI0Divxyvd2QWB7/ZcF7JKwMssWI6/zZzlMkq/Pt6ow2AOEebPw=="], + "@smithy/config-resolver": ["@smithy/config-resolver@4.3.0", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.0", "@smithy/types": "^4.6.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-middleware": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-9oH+n8AVNiLPK/iK/agOsoWfrKZ3FGP3502tkksd6SRsKMYiu7AFX0YXo6YBADdsAj7C+G/aLKdsafIJHxuCkQ=="], - "@smithy/core": ["@smithy/core@3.16.1", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.2", "@smithy/protocol-http": "^5.3.2", "@smithy/types": "^4.7.1", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.2", "@smithy/util-stream": "^4.5.2", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-yRx5ag3xEQ/yGvyo80FVukS7ZkeUP49Vbzg0MjfHLkuCIgg5lFtaEJfZR178KJmjWPqLU4d0P4k7SKgF9UkOaQ=="], + "@smithy/core": ["@smithy/core@3.15.0", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.0", "@smithy/protocol-http": "^5.3.0", "@smithy/types": "^4.6.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.0", "@smithy/util-stream": "^4.5.0", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-VJWncXgt+ExNn0U2+Y7UywuATtRYaodGQKFo9mDyh70q+fJGedfrqi2XuKU1BhiLeXgg6RZrW7VEKfeqFhHAJA=="], - "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.2", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.2", "@smithy/property-provider": "^4.2.2", "@smithy/types": "^4.7.1", "@smithy/url-parser": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-hOjFTK+4mfehDnfjNkPqHUKBKR2qmlix5gy7YzruNbTdeoBE3QkfNCPvuCK2r05VUJ02QQ9bz2G41CxhSexsMw=="], + "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.0", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.0", "@smithy/property-provider": "^4.2.0", "@smithy/types": "^4.6.0", "@smithy/url-parser": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-SOhFVvFH4D5HJZytb0bLKxCrSnwcqPiNlrw+S4ZXjMnsC+o9JcUQzbZOEQcA8yv9wJFNhfsUiIUKiEnYL68Big=="], - "@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.2", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.7.1", "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-TDJFBixL6p/CZ6VyTfU+9YrPtcriAouv2IECk5jM4Y3zRJYXyei8lvsCSMMgYW9mLMbtp3mvJbeI8SLOF2BunA=="], + "@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.0", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.6.0", "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-XE7CtKfyxYiNZ5vz7OvyTf1osrdbJfmUy+rbh+NLQmZumMGvY0mT0Cq1qKSfhrvLtRYzMsOBuRpi10dyI0EBPg=="], - "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.3", "", { "dependencies": { "@smithy/protocol-http": "^5.3.2", "@smithy/querystring-builder": "^4.2.2", "@smithy/types": "^4.7.1", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-cipIcM3xQ5NdIVwcRb37LaQwIxZNMEZb/ZOPmLFS9uGo9TGx2dGCyMBj9oT7ypH4TUD/kOTc/qHmwQzthrSk+g=="], + "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.1", "", { "dependencies": { "@smithy/protocol-http": "^5.3.0", "@smithy/querystring-builder": "^4.2.0", "@smithy/types": "^4.6.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-3AvYYbB+Dv5EPLqnJIAgYw/9+WzeBiUYS8B+rU0pHq5NMQMvrZmevUROS4V2GAt0jEOn9viBzPLrZE+riTNd5Q=="], - "@smithy/hash-node": ["@smithy/hash-node@4.2.2", "", { "dependencies": { "@smithy/types": "^4.7.1", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-xuOPGrF2GUP+9og5NU02fplRVjJjMhAaY8ZconB3eLKjv/VSV9/s+sFf72MYO5Q2jcSRVk/ywZHpyGbE3FYnFQ=="], + "@smithy/hash-node": ["@smithy/hash-node@4.2.0", "", { "dependencies": { "@smithy/types": "^4.6.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-ugv93gOhZGysTctZh9qdgng8B+xO0cj+zN0qAZ+Sgh7qTQGPOJbMdIuyP89KNfUyfAqFSNh5tMvC+h2uCpmTtA=="], - "@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.2", "", { "dependencies": { "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-Z0844Zpoid5L1DmKX2+cn2Qu9i3XWjhzwYBRJEWrKJwjUuhEkzf37jKPj9dYFsZeKsAbS2qI0JyLsYafbXJvpA=="], + "@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.0", "", { "dependencies": { "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-ZmK5X5fUPAbtvRcUPtk28aqIClVhbfcmfoS4M7UQBTnDdrNxhsrxYVv0ZEl5NaPSyExsPWqL4GsPlRvtlwg+2A=="], "@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], - "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.2", "", { "dependencies": { "@smithy/protocol-http": "^5.3.2", "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-aJ7LAuIXStF6EqzRVX9kAW+6/sYoJJv0QqoFrz2BhA9r/85kLYOJ6Ph47wYSGBxzSLxsYT5jqgMw/qpbv1+m+w=="], + "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.0", "", { "dependencies": { "@smithy/protocol-http": "^5.3.0", "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-6ZAnwrXFecrA4kIDOcz6aLBhU5ih2is2NdcZtobBDSdSHtE9a+MThB5uqyK4XXesdOCvOcbCm2IGB95birTSOQ=="], - "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.3.3", "", { "dependencies": { "@smithy/core": "^3.16.1", "@smithy/middleware-serde": "^4.2.2", "@smithy/node-config-provider": "^4.3.2", "@smithy/shared-ini-file-loader": "^4.3.2", "@smithy/types": "^4.7.1", "@smithy/url-parser": "^4.2.2", "@smithy/util-middleware": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-CfxQ6X9L87/3C67Po6AGWXsx8iS4w2BO8vQEZJD6hwqg2vNRC/lMa2O5wXYCG9tKotdZ0R8KG33TS7kpUnYKiw=="], + "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.3.1", "", { "dependencies": { "@smithy/core": "^3.15.0", "@smithy/middleware-serde": "^4.2.0", "@smithy/node-config-provider": "^4.3.0", "@smithy/shared-ini-file-loader": "^4.3.0", "@smithy/types": "^4.6.0", "@smithy/url-parser": "^4.2.0", "@smithy/util-middleware": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-JtM4SjEgImLEJVXdsbvWHYiJ9dtuKE8bqLlvkvGi96LbejDL6qnVpVxEFUximFodoQbg0Gnkyff9EKUhFhVJFw=="], - "@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.3", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.2", "@smithy/protocol-http": "^5.3.2", "@smithy/service-error-classification": "^4.2.2", "@smithy/smithy-client": "^4.8.1", "@smithy/types": "^4.7.1", "@smithy/util-middleware": "^4.2.2", "@smithy/util-retry": "^4.2.2", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-EHnKGeFuzbmER4oSl/VJDxPLi+aiZUb3nk5KK8eNwHjMhI04jHlui2ZkaBzMfNmXOgymaS6zV//fyt6PSnI1ow=="], + "@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.1", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.0", "@smithy/protocol-http": "^5.3.0", "@smithy/service-error-classification": "^4.2.0", "@smithy/smithy-client": "^4.7.1", "@smithy/types": "^4.6.0", "@smithy/util-middleware": "^4.2.0", "@smithy/util-retry": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-wXxS4ex8cJJteL0PPQmWYkNi9QKDWZIpsndr0wZI2EL+pSSvA/qqxXU60gBOJoIc2YgtZSWY/PE86qhKCCKP1w=="], - "@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.2", "", { "dependencies": { "@smithy/protocol-http": "^5.3.2", "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-tDMPMBCsA1GBxanShhPvQYwdiau3NmctUp+eELMhUTDua+EUrugXlaKCnTMMoEB5mbHFebdv81uJPkVP02oihA=="], + "@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.0", "", { "dependencies": { "@smithy/protocol-http": "^5.3.0", "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-rpTQ7D65/EAbC6VydXlxjvbifTf4IH+sADKg6JmAvhkflJO2NvDeyU9qsWUNBelJiQFcXKejUHWRSdmpJmEmiw=="], - "@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.2", "", { "dependencies": { "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-7rgzDyLOQouh1bC6gOXnCGSX2dqvbOclgClsFkj735xQM2CHV63Ams8odNZGJgcqnBsEz44V/pDGHU6ALEUD+w=="], + "@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.0", "", { "dependencies": { "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-G5CJ//eqRd9OARrQu9MK1H8fNm2sMtqFh6j8/rPozhEL+Dokpvi1Og+aCixTuwDAGZUkJPk6hJT5jchbk/WCyg=="], - "@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.2", "", { "dependencies": { "@smithy/property-provider": "^4.2.2", "@smithy/shared-ini-file-loader": "^4.3.2", "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-u38G0Audi2ORsL0QnzhopZ3yweMblQf8CZNbzUJ3wfTtZ7OiOwOzee0Nge/3dKeG/8lx0kt8K0kqDi6sYu0oKQ=="], + "@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.0", "", { "dependencies": { "@smithy/property-provider": "^4.2.0", "@smithy/shared-ini-file-loader": "^4.3.0", "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-5QgHNuWdT9j9GwMPPJCKxy2KDxZ3E5l4M3/5TatSZrqYVoEiqQrDfAq8I6KWZw7RZOHtVtCzEPdYz7rHZixwcA=="], - "@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.1", "", { "dependencies": { "@smithy/abort-controller": "^4.2.2", "@smithy/protocol-http": "^5.3.2", "@smithy/querystring-builder": "^4.2.2", "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-9gKJoL45MNyOCGTG082nmx0A6KrbLVQ+5QSSKyzRi0AzL0R81u3wC1+nPvKXgTaBdAKM73fFPdCBHpmtipQwdQ=="], + "@smithy/node-http-handler": ["@smithy/node-http-handler@4.3.0", "", { "dependencies": { "@smithy/abort-controller": "^4.2.0", "@smithy/protocol-http": "^5.3.0", "@smithy/querystring-builder": "^4.2.0", "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-RHZ/uWCmSNZ8cneoWEVsVwMZBKy/8123hEpm57vgGXA3Irf/Ja4v9TVshHK2ML5/IqzAZn0WhINHOP9xl+Qy6Q=="], - "@smithy/property-provider": ["@smithy/property-provider@4.2.2", "", { "dependencies": { "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-MW7MfI+qYe/Ue5RH0uEztEKB+vBlOMM+1Dz68qzTsY8fC9kanXMFPEVdiq35JTGKWt5wZAjU1R0uXYEjK2MM1g=="], + "@smithy/property-provider": ["@smithy/property-provider@4.2.0", "", { "dependencies": { "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-rV6wFre0BU6n/tx2Ztn5LdvEdNZ2FasQbPQmDOPfV9QQyDmsCkOAB0osQjotRCQg+nSKFmINhyda0D3AnjSBJw=="], - "@smithy/protocol-http": ["@smithy/protocol-http@5.3.2", "", { "dependencies": { "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-nkKOI8xEkBXUmdxsFExomOb+wkU+Xgn0Fq2LMC7YIX5r4YPUg7PLayV/s/u3AtbyjWYlrvN7nAiDTLlqSdUjHw=="], + "@smithy/protocol-http": ["@smithy/protocol-http@5.3.0", "", { "dependencies": { "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-6POSYlmDnsLKb7r1D3SVm7RaYW6H1vcNcTWGWrF7s9+2noNYvUsm7E4tz5ZQ9HXPmKn6Hb67pBDRIjrT4w/d7Q=="], - "@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.2", "", { "dependencies": { "@smithy/types": "^4.7.1", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-YgXvq89o+R/8zIoeuXYv8Ysrbwgjx+iVYu9QbseqZjMDAhIg/FRt7jis0KASYFtd/Cnsnz4/nYTJXkJDWe8wHg=="], + "@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.0", "", { "dependencies": { "@smithy/types": "^4.6.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Q4oFD0ZmI8yJkiPPeGUITZj++4HHYCW3pYBYfIobUCkYpI6mbkzmG1MAQQ3lJYYWj3iNqfzOenUZu+jqdPQ16A=="], - "@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.2", "", { "dependencies": { "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-DczOD2yJy3NXcv1JvhjFC7bIb/tay6nnIRD/qrzBaju5lrkVBOwCT3Ps37tra20wy8PicZpworStK7ZcI9pCRQ=="], + "@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.0", "", { "dependencies": { "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-BjATSNNyvVbQxOOlKse0b0pSezTWGMvA87SvoFoFlkRsKXVsN3bEtjCxvsNXJXfnAzlWFPaT9DmhWy1vn0sNEA=="], - "@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.2", "", { "dependencies": { "@smithy/types": "^4.7.1" } }, "sha512-1X17cMLwe/vb4RpZbQVpJ1xQQ7fhQKggMdt3qjdV3+6QNllzvUXyS3WFnyaFWLyaGqfYHKkNONbO1fBCMQyZtQ=="], + "@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.0", "", { "dependencies": { "@smithy/types": "^4.6.0" } }, "sha512-Ylv1ttUeKatpR0wEOMnHf1hXMktPUMObDClSWl2TpCVT4DwtJhCeighLzSLbgH3jr5pBNM0LDXT5yYxUvZ9WpA=="], - "@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.3.2", "", { "dependencies": { "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-AWnLgSmOTdDXM8aZCN4Im0X07M3GGffeL9vGfea4mdKZD0cPT9yLF9SsRbEa00tHLI+KfubDrmjpaKT2pM4GdQ=="], + "@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.3.0", "", { "dependencies": { "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-VCUPPtNs+rKWlqqntX0CbVvWyjhmX30JCtzO+s5dlzzxrvSfRh5SY0yxnkirvc1c80vdKQttahL71a9EsdolSQ=="], - "@smithy/signature-v4": ["@smithy/signature-v4@5.3.2", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.2", "@smithy/types": "^4.7.1", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.2", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-BRnQGGyaRSSL0KtjjFF9YoSSg8qzSqHMub4H2iKkd+LZNzZ1b7H5amslZBzi+AnvuwPMyeiNv0oqay/VmIuoRA=="], + "@smithy/signature-v4": ["@smithy/signature-v4@5.3.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.0", "@smithy/types": "^4.6.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.0", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-MKNyhXEs99xAZaFhm88h+3/V+tCRDQ+PrDzRqL0xdDpq4gjxcMmf5rBA3YXgqZqMZ/XwemZEurCBQMfxZOWq/g=="], - "@smithy/smithy-client": ["@smithy/smithy-client@4.8.1", "", { "dependencies": { "@smithy/core": "^3.16.1", "@smithy/middleware-endpoint": "^4.3.3", "@smithy/middleware-stack": "^4.2.2", "@smithy/protocol-http": "^5.3.2", "@smithy/types": "^4.7.1", "@smithy/util-stream": "^4.5.2", "tslib": "^2.6.2" } }, "sha512-N5wK57pVThzLVK5NgmHxocTy5auqGDGQ+JsL5RjCTriPt8JLYgXT0Awa915zCpzc9hXHDOKqDX5g9BFdwkSfUA=="], + "@smithy/smithy-client": ["@smithy/smithy-client@4.7.1", "", { "dependencies": { "@smithy/core": "^3.15.0", "@smithy/middleware-endpoint": "^4.3.1", "@smithy/middleware-stack": "^4.2.0", "@smithy/protocol-http": "^5.3.0", "@smithy/types": "^4.6.0", "@smithy/util-stream": "^4.5.0", "tslib": "^2.6.2" } }, "sha512-WXVbiyNf/WOS/RHUoFMkJ6leEVpln5ojCjNBnzoZeMsnCg3A0BRhLK3WYc4V7PmYcYPZh9IYzzAg9XcNSzYxYQ=="], - "@smithy/types": ["@smithy/types@4.7.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-WwP7vzoDyzvIFLzF5UhLQ6AsEx/PvSObzlNtJNW3lLy+BaSvTqCU628QKVvcJI/dydlAS1mSHQP7anKcxDcOxA=="], + "@smithy/types": ["@smithy/types@4.6.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-4lI9C8NzRPOv66FaY1LL1O/0v0aLVrq/mXP/keUa9mJOApEeae43LsLd2kZRUJw91gxOQfLIrV3OvqPgWz1YsA=="], - "@smithy/url-parser": ["@smithy/url-parser@4.2.2", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.2", "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-s2EYKukaswzjiHJCss6asB1F4zjRc0E/MFyceAKzb3+wqKA2Z/+Gfhb5FP8xVVRHBAvBkregaQAydifgbnUlCw=="], + "@smithy/url-parser": ["@smithy/url-parser@4.2.0", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.0", "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-AlBmD6Idav2ugmoAL6UtR6ItS7jU5h5RNqLMZC7QrLCoITA9NzIN3nx9GWi8g4z1pfWh2r9r96SX/jHiNwPJ9A=="], "@smithy/util-base64": ["@smithy/util-base64@4.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ=="], @@ -1234,19 +1235,19 @@ "@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="], - "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.2", "", { "dependencies": { "@smithy/property-provider": "^4.2.2", "@smithy/smithy-client": "^4.8.1", "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-6JvKHZ5GORYkEZ2+yJKEHp6dQQKng+P/Mu3g3CDy0fRLQgXEO8be+FLrBGGb4kB9lCW6wcQDkN7kRiGkkVAXgg=="], + "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.0", "", { "dependencies": { "@smithy/property-provider": "^4.2.0", "@smithy/smithy-client": "^4.7.1", "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-H4MAj8j8Yp19Mr7vVtGgi7noJjvjJbsKQJkvNnLlrIFduRFT5jq5Eri1k838YW7rN2g5FTnXpz5ktKVr1KVgPQ=="], - "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.3", "", { "dependencies": { "@smithy/config-resolver": "^4.3.2", "@smithy/credential-provider-imds": "^4.2.2", "@smithy/node-config-provider": "^4.3.2", "@smithy/property-provider": "^4.2.2", "@smithy/smithy-client": "^4.8.1", "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-bkTGuMmKvghfCh9NayADrQcjngoF8P+XTgID5r3rm+8LphFiuM6ERqpBS95YyVaLjDetnKus9zK/bGlkQOOtNQ=="], + "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.1", "", { "dependencies": { "@smithy/config-resolver": "^4.3.0", "@smithy/credential-provider-imds": "^4.2.0", "@smithy/node-config-provider": "^4.3.0", "@smithy/property-provider": "^4.2.0", "@smithy/smithy-client": "^4.7.1", "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-PuDcgx7/qKEMzV1QFHJ7E4/MMeEjaA7+zS5UNcHCLPvvn59AeZQ0DSDGMpqC2xecfa/1cNGm4l8Ec/VxCuY7Ug=="], - "@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.2", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.2", "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-ZQi6fFTMBkfwwSPAlcGzArmNILz33QH99CL8jDfVWrzwVVcZc56Mge10jGk0zdRgWPXyL1/OXKjfw4vT5VtRQg=="], + "@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.0", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.0", "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-TXeCn22D56vvWr/5xPqALc9oO+LN+QpFjrSM7peG/ckqEPoI3zaKZFp+bFwfmiHhn5MGWPaLCqDOJPPIixk9Wg=="], "@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], - "@smithy/util-middleware": ["@smithy/util-middleware@4.2.2", "", { "dependencies": { "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-wL9tZwWKy0x0qf6ffN7tX5CT03hb1e7XpjdepaKfKcPcyn5+jHAWPqivhF1Sw/T5DYi9wGcxsX8Lu07MOp2Puw=="], + "@smithy/util-middleware": ["@smithy/util-middleware@4.2.0", "", { "dependencies": { "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-u9OOfDa43MjagtJZ8AapJcmimP+K2Z7szXn8xbty4aza+7P1wjFmy2ewjSbhEiYQoW1unTlOAIV165weYAaowA=="], - "@smithy/util-retry": ["@smithy/util-retry@4.2.2", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.2", "@smithy/types": "^4.7.1", "tslib": "^2.6.2" } }, "sha512-TlbnWAOoCuG2PgY0Hi3BGU1w2IXs3xDsD4E8WDfKRZUn2qx3wRA9mbYnmpWHPswTJCz2L+ebh+9OvD42sV4mNw=="], + "@smithy/util-retry": ["@smithy/util-retry@4.2.0", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.0", "@smithy/types": "^4.6.0", "tslib": "^2.6.2" } }, "sha512-BWSiuGbwRnEE2SFfaAZEX0TqaxtvtSYPM/J73PFVm+A29Fg1HTPiYFb8TmX1DXp4hgcdyJcNQmprfd5foeORsg=="], - "@smithy/util-stream": ["@smithy/util-stream@4.5.2", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.3", "@smithy/node-http-handler": "^4.4.1", "@smithy/types": "^4.7.1", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-RWYVuQVKtNbr7E0IxV8XHDId714yHPTxU6dHScd6wSMWAXboErzTG7+xqcL+K3r0Xg0cZSlfuNhl1J0rzMLSSw=="], + "@smithy/util-stream": ["@smithy/util-stream@4.5.0", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.1", "@smithy/node-http-handler": "^4.3.0", "@smithy/types": "^4.6.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-0TD5M5HCGu5diEvZ/O/WquSjhJPasqv7trjoqHyWjNh/FBeBl7a0ztl9uFMOsauYtRfd8jvpzIAQhDHbx+nvZw=="], "@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], @@ -1332,6 +1333,32 @@ "@tanstack/server-functions-plugin": ["@tanstack/server-functions-plugin@1.121.21", "", { "dependencies": { "@babel/code-frame": "7.26.2", "@babel/core": "^7.26.8", "@babel/plugin-syntax-jsx": "^7.25.9", "@babel/plugin-syntax-typescript": "^7.25.9", "@babel/template": "^7.26.8", "@babel/traverse": "^7.26.8", "@babel/types": "^7.26.8", "@tanstack/directive-functions-plugin": "1.121.21", "babel-dead-code-elimination": "^1.0.9", "tiny-invariant": "^1.3.3" } }, "sha512-a05fzK+jBGacsSAc1vE8an7lpBh4H0PyIEcivtEyHLomgSeElAJxm9E2It/0nYRZ5Lh23m0okbhzJNaYWZpAOg=="], + "@tauri-apps/api": ["@tauri-apps/api@2.8.0", "", {}, "sha512-ga7zdhbS2GXOMTIZRT0mYjKJtR9fivsXzsyq5U3vjDL0s6DTMwYRm0UHNjzTY5dh4+LSC68Sm/7WEiimbQNYlw=="], + + "@tauri-apps/cli": ["@tauri-apps/cli@2.8.4", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.8.4", "@tauri-apps/cli-darwin-x64": "2.8.4", "@tauri-apps/cli-linux-arm-gnueabihf": "2.8.4", "@tauri-apps/cli-linux-arm64-gnu": "2.8.4", "@tauri-apps/cli-linux-arm64-musl": "2.8.4", "@tauri-apps/cli-linux-riscv64-gnu": "2.8.4", "@tauri-apps/cli-linux-x64-gnu": "2.8.4", "@tauri-apps/cli-linux-x64-musl": "2.8.4", "@tauri-apps/cli-win32-arm64-msvc": "2.8.4", "@tauri-apps/cli-win32-ia32-msvc": "2.8.4", "@tauri-apps/cli-win32-x64-msvc": "2.8.4" }, "bin": { "tauri": "tauri.js" } }, "sha512-ejUZBzuQRcjFV+v/gdj/DcbyX/6T4unZQjMSBZwLzP/CymEjKcc2+Fc8xTORThebHDUvqoXMdsCZt8r+hyN15g=="], + + "@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.8.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BKu8HRkYV01SMTa7r4fLx+wjgtRK8Vep7lmBdHDioP6b8XH3q2KgsAyPWfEZaZIkZ2LY4SqqGARaE9oilNe0oA=="], + + "@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.8.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-imb9PfSd/7G6VAO7v1bQ2A3ZH4NOCbhGJFLchxzepGcXf9NKkfun157JH9mko29K6sqAwuJ88qtzbKCbWJTH9g=="], + + "@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.8.4", "", { "os": "linux", "cpu": "arm" }, "sha512-Ml215UnDdl7/fpOrF1CNovym/KjtUbCuPgrcZ4IhqUCnhZdXuphud/JT3E8X97Y03TZ40Sjz8raXYI2ET0exzw=="], + + "@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.8.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-pbcgBpMyI90C83CxE5REZ9ODyIlmmAPkkJXtV398X3SgZEIYy5TACYqlyyv2z5yKgD8F8WH4/2fek7+jH+ZXAw=="], + + "@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.8.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-zumFeaU1Ws5Ay872FTyIm7z8kfzEHu8NcIn8M6TxbJs0a7GRV21KBdpW1zNj2qy7HynnpQCqjAYXTUUmm9JAOw=="], + + "@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.8.4", "", { "os": "linux", "cpu": "none" }, "sha512-qiqbB3Zz6IyO201f+1ojxLj65WYj8mixL5cOMo63nlg8CIzsP23cPYUrx1YaDPsCLszKZo7tVs14pc7BWf+/aQ=="], + + "@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.8.4", "", { "os": "linux", "cpu": "x64" }, "sha512-TaqaDd9Oy6k45Hotx3pOf+pkbsxLaApv4rGd9mLuRM1k6YS/aw81YrsMryYPThrxrScEIUcmNIHaHsLiU4GMkw=="], + + "@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.8.4", "", { "os": "linux", "cpu": "x64" }, "sha512-ot9STAwyezN8w+bBHZ+bqSQIJ0qPZFlz/AyscpGqB/JnJQVDFQcRDmUPFEaAtt2UUHSWzN3GoTJ5ypqLBp2WQA=="], + + "@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.8.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-+2aJ/g90dhLiOLFSD1PbElXX3SoMdpO7HFPAZB+xot3CWlAZD1tReUFy7xe0L5GAR16ZmrxpIDM9v9gn5xRy/w=="], + + "@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.8.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-yj7WDxkL1t9Uzr2gufQ1Hl7hrHuFKTNEOyascbc109EoiAqCp0tgZ2IykQqOZmZOHU884UAWI1pVMqBhS/BfhA=="], + + "@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.8.4", "", { "os": "win32", "cpu": "x64" }, "sha512-XuvGB4ehBdd7QhMZ9qbj/8icGEatDuBNxyYHbLKsTYh90ggUlPa/AtaqcC1Fo69lGkTmq9BOKrs1aWSi7xDonA=="], + "@thisbeyond/solid-dnd": ["@thisbeyond/solid-dnd@0.7.5", "", { "peerDependencies": { "solid-js": "^1.5" } }, "sha512-DfI5ff+yYGpK9M21LhYwIPlbP2msKxN2ARwuu6GF8tT1GgNVDTI8VCQvH4TJFoVApP9d44izmAcTh/iTCH2UUw=="], "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], @@ -1584,7 +1611,7 @@ "bare-stream": ["bare-stream@2.7.0", "", { "dependencies": { "streamx": "^2.21.0" }, "peerDependencies": { "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-buffer", "bare-events"] }, "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A=="], - "bare-url": ["bare-url@2.3.0", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-c+RCqMSZbkz97Mw1LWR0gcOqwK82oyYKfLoHJ8k13ybi1+I80ffdDzUy0TdAburdrR/kI0/VuN8YgEnJqX+Nyw=="], + "bare-url": ["bare-url@2.2.2", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-g+ueNGKkrjMazDG3elZO1pNs3HY5+mMmOet1jtKyhOaCnkLzitxf26z7hoAEkDNgdNmnc1KIlt/dw6Po6xZMpA=="], "base-64": ["base-64@1.0.0", "", {}, "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="], @@ -1666,7 +1693,7 @@ "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], - "caniuse-lite": ["caniuse-lite@1.0.30001750", "", {}, "sha512-cuom0g5sdX6rw00qOoLNSFCJ9/mYIsuSOA+yzpDw8eopiFqcVwQvZHqov0vmEighRxX++cfC0Vg1G+1Iy/mSpQ=="], + "caniuse-lite": ["caniuse-lite@1.0.30001749", "", {}, "sha512-0rw2fJOmLfnzCRbkm8EyHL8SvI2Apu5UbnQuTsJ0ClgrH8hcwFooJ1s5R0EP8o8aVrFu8++ae29Kt9/gZAZp/Q=="], "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], @@ -1734,6 +1761,8 @@ "compress-commons": ["compress-commons@6.0.2", "", { "dependencies": { "crc-32": "^1.2.0", "crc32-stream": "^6.0.0", "is-stream": "^2.0.1", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg=="], + "concurrently": ["concurrently@9.2.1", "", { "dependencies": { "chalk": "4.1.2", "rxjs": "7.8.2", "shell-quote": "1.8.3", "supports-color": "8.1.1", "tree-kill": "1.2.2", "yargs": "17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" } }, "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng=="], + "condense-newlines": ["condense-newlines@0.2.1", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-whitespace": "^0.3.0", "kind-of": "^3.0.2" } }, "sha512-P7X+QL9Hb9B/c8HI5BFFKmjgBu2XpQuF98WZ9XkO+dBGgk5XgwiQz7o1SmpglNWId3581UcS0SFAWfoIhMHPfg=="], "confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="], @@ -1882,9 +1911,9 @@ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - "electron-to-chromium": ["electron-to-chromium@1.5.235", "", {}, "sha512-i/7ntLFwOdoHY7sgjlTIDo4Sl8EdoTjWIaKinYOVfC6bOp71bmwenyZthWHcasxgHDNWbWxvG9M3Ia116zIaYQ=="], + "electron-to-chromium": ["electron-to-chromium@1.5.234", "", {}, "sha512-RXfEp2x+VRYn8jbKfQlRImzoJU01kyDvVPBmG39eU2iuRVhuS6vQNocB8J0/8GrIMLnPzgz4eW6WiRnJkTuNWg=="], - "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], + "emoji-regex": ["emoji-regex@10.5.0", "", {}, "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg=="], "emoji-regex-xs": ["emoji-regex-xs@1.0.0", "", {}, "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg=="], @@ -3026,6 +3055,8 @@ "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="], + "s-js": ["s-js@0.4.9", "", {}, "sha512-RtpOm+cM6O0sHg6IA70wH+UC3FZcND+rccBZpBAHzlUgNO2Bm5BN+FnM8+OBxzXdwpKWFwX11JGF0MFRkhSoIQ=="], "safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="], @@ -3164,7 +3195,7 @@ "statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], - "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="], + "std-env": ["std-env@3.9.0", "", {}, "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="], "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="], @@ -3214,7 +3245,7 @@ "superstruct": ["superstruct@1.0.4", "", {}, "sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ=="], - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], @@ -3268,6 +3299,8 @@ "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + "tree-sitter": ["tree-sitter@0.22.4", "", { "dependencies": { "node-addon-api": "^8.3.0", "node-gyp-build": "^4.8.4" } }, "sha512-usbHZP9/oxNsUY65MQUsduGRqDHQOou1cagUSwjhoSYAmSahjQDAVsh9s+SlZkn8X8+O1FULRGwHu7AFP3kjzg=="], "tree-sitter-bash": ["tree-sitter-bash@0.23.3", "", { "dependencies": { "node-addon-api": "^8.2.1", "node-gyp-build": "^4.8.2" }, "peerDependencies": { "tree-sitter": "^0.21.1" }, "optionalPeers": ["tree-sitter"] }, "sha512-36cg/GQ2YmIbeiBeqeuh4fBJ6i4kgVouDaqTxqih5ysPag+zHufyIaxMOFeM8CeplwAK/Luj1o5XHqgdAfoCZg=="], @@ -3432,13 +3465,13 @@ "virtua": ["virtua@0.42.3", "", { "peerDependencies": { "react": ">=16.14.0", "react-dom": ">=16.14.0", "solid-js": ">=1.0", "svelte": ">=5.0", "vue": ">=3.2" }, "optionalPeers": ["react", "react-dom", "solid-js", "svelte", "vue"] }, "sha512-5FoAKcEvh05qsUF97Yz42SWJ7bwnPExjUYHGuoxz1EUtfWtaOgXaRwnylJbDpA0QcH1rKvJ2qsGRi9MK1fpQbg=="], - "vite": ["vite@7.1.4", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw=="], + "vite": ["vite@6.3.6", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA=="], "vite-plugin-dynamic-import": ["vite-plugin-dynamic-import@1.6.0", "", { "dependencies": { "acorn": "^8.12.1", "es-module-lexer": "^1.5.4", "fast-glob": "^3.3.2", "magic-string": "^0.30.11" } }, "sha512-TM0sz70wfzTIo9YCxVFwS8OA9lNREsh+0vMHGSkWDTZ7bgd1Yjs5RV8EgB634l/91IsXJReg0xtmuQqP0mf+rg=="], "vite-plugin-icons-spritesheet": ["vite-plugin-icons-spritesheet@3.0.1", "", { "dependencies": { "chalk": "^5.4.1", "glob": "^11.0.1", "node-html-parser": "^7.0.1", "tinyexec": "^0.3.2" }, "peerDependencies": { "vite": ">=5.2.0" } }, "sha512-Cr0+Z6wRMwSwKisWW9PHeTjqmQFv0jwRQQMc3YgAhAgZEe03j21el0P/CA31KN/L5eiL1LhR14VTXl96LetonA=="], - "vite-plugin-solid": ["vite-plugin-solid@2.11.8", "", { "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" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-hFrCxBfv3B1BmFqnJF4JOCYpjrmi/zwyeKjcomQ0khh8HFyQ8SbuBWQ7zGojfrz6HUOBFrJBNySDi/JgAHytWg=="], + "vite-plugin-solid": ["vite-plugin-solid@2.11.9", "", { "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" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-bTA6p+bspXZsuulSd2y6aTzegF8xGaJYcq1Uyh/mv+W4DQtzCgL9nN6n2fsTaxp/dMk+ZHHKgGndlNeooqHLKw=="], "vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="], @@ -3484,7 +3517,7 @@ "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - "ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], + "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=="], "xdg-basedir": ["xdg-basedir@5.1.0", "", {}, "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ=="], @@ -3542,16 +3575,12 @@ "@ai-sdk/google-vertex/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.7", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-o3BS5/t8KnBL3ubP8k3w77AByOypLm+pkIL/DCw0qKkhDbvhCy+L3hRTGPikpdb8WHcylAeKsjgwOxhj4cqTUA=="], - "@astrojs/cloudflare/vite": ["vite@6.3.7", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-mQYaKepA0NGMBsz8Xktt3tJUG5ELE2iT7IJ+ssXI6nxVdE2sFc/d/6w/JByqMLvWg8hNKHpPgzjgOkrhpKFnrA=="], - "@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="], "@astrojs/mdx/@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.8", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.4", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.13.0", "smol-toml": "^1.4.2", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-uFNyFWadnULWK2cOw4n0hLKeu+xaVWeuECdP10cQ3K2fkybtTlhb7J7TcScdjmS8Yps7oje9S/ehYMfZrhrgCg=="], "@astrojs/sitemap/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "@astrojs/solid-js/vite": ["vite@6.3.7", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-mQYaKepA0NGMBsz8Xktt3tJUG5ELE2iT7IJ+ssXI6nxVdE2sFc/d/6w/JByqMLvWg8hNKHpPgzjgOkrhpKFnrA=="], - "@aws-crypto/sha256-browser/@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-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=="], @@ -3658,6 +3687,10 @@ "@openauthjs/openauth/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="], + "@opencode-ai/ui/vite": ["vite@7.1.4", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw=="], + + "@opencode-ai/ui/vite-plugin-solid": ["vite-plugin-solid@2.11.8", "", { "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" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-hFrCxBfv3B1BmFqnJF4JOCYpjrmi/zwyeKjcomQ0khh8HFyQ8SbuBWQ7zGojfrz6HUOBFrJBNySDi/JgAHytWg=="], + "@opencode-ai/web/@shikijs/transformers": ["@shikijs/transformers@3.4.2", "", { "dependencies": { "@shikijs/core": "3.4.2", "@shikijs/types": "3.4.2" } }, "sha512-I5baLVi/ynLEOZoWSAMlACHNnG+yw5HDmse0oe+GW6U1u+ULdEB3UHiVWaHoJSSONV7tlcVxuaMy74sREDkSvg=="], "@opencode-ai/web/@types/luxon": ["@types/luxon@3.6.2", "", {}, "sha512-R/BdP7OxEMc44l2Ex5lSXHoIXTB2JLNa3y2QISIbr58U/YcsffyQrYW//hZSdrfxrjRZj3GcUoxMPGdO8gSYuw=="], @@ -3692,6 +3725,8 @@ "@slack/socket-mode/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + "@slack/socket-mode/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], + "@slack/web-api/@slack/logger": ["@slack/logger@3.0.0", "", { "dependencies": { "@types/node": ">=12.0.0" } }, "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA=="], "@slack/web-api/eventemitter3": ["eventemitter3@3.1.2", "", {}, "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="], @@ -3750,8 +3785,6 @@ "astro/sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], - "astro/vite": ["vite@6.3.7", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-mQYaKepA0NGMBsz8Xktt3tJUG5ELE2iT7IJ+ssXI6nxVdE2sFc/d/6w/JByqMLvWg8hNKHpPgzjgOkrhpKFnrA=="], - "astro/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "axios/form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="], @@ -3782,10 +3815,14 @@ "c12/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "clean-css/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "compress-commons/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + "concurrently/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + "condense-newlines/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], @@ -3794,7 +3831,7 @@ "dir-glob/path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], - "dot-prop/type-fest": ["type-fest@5.1.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-wQ531tuWvB6oK+pchHIu5lHe5f5wpSCqB8Kf4dWQRbOYc9HTge7JL0G4Qd44bh6QuJCccIzL3bugb8GI0MwHrg=="], + "dot-prop/type-fest": ["type-fest@5.0.1", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-9MpwAI52m8H6ssA542UxSLnSiSD2dsC3/L85g6hVubLSXd82wdI80eZwTWhdOfN67NlA+D+oipAs1MlcTcu3KA=="], "drizzle-kit/esbuild": ["esbuild@0.19.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.19.12", "@esbuild/android-arm": "0.19.12", "@esbuild/android-arm64": "0.19.12", "@esbuild/android-x64": "0.19.12", "@esbuild/darwin-arm64": "0.19.12", "@esbuild/darwin-x64": "0.19.12", "@esbuild/freebsd-arm64": "0.19.12", "@esbuild/freebsd-x64": "0.19.12", "@esbuild/linux-arm": "0.19.12", "@esbuild/linux-arm64": "0.19.12", "@esbuild/linux-ia32": "0.19.12", "@esbuild/linux-loong64": "0.19.12", "@esbuild/linux-mips64el": "0.19.12", "@esbuild/linux-ppc64": "0.19.12", "@esbuild/linux-riscv64": "0.19.12", "@esbuild/linux-s390x": "0.19.12", "@esbuild/linux-x64": "0.19.12", "@esbuild/netbsd-x64": "0.19.12", "@esbuild/openbsd-x64": "0.19.12", "@esbuild/sunos-x64": "0.19.12", "@esbuild/win32-arm64": "0.19.12", "@esbuild/win32-ia32": "0.19.12", "@esbuild/win32-x64": "0.19.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg=="], @@ -3864,8 +3901,6 @@ "miniflare/sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], - "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/youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="], "miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], @@ -4018,8 +4053,6 @@ "utif2/pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="], - "vinxi/vite": ["vite@6.3.7", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-mQYaKepA0NGMBsz8Xktt3tJUG5ELE2iT7IJ+ssXI6nxVdE2sFc/d/6w/JByqMLvWg8hNKHpPgzjgOkrhpKFnrA=="], - "vinxi/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "vite-plugin-icons-spritesheet/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], @@ -4036,6 +4069,8 @@ "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "xml2js/sax": ["sax@1.4.1", "", {}, "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="], + "yargs/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="], "zod-to-json-schema/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -4194,6 +4229,8 @@ "@modelcontextprotocol/sdk/express/serve-static": ["serve-static@2.2.0", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ=="], + "@modelcontextprotocol/sdk/express/statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], + "@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=="], "@octokit/auth-oauth-app/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@26.0.0", "", {}, "sha512-7AtcfKtpo77j7Ts73b4OWhOZHTKo/gGY8bB3bNBQz4H+GRSWqx2yvj8TXRsbdTE0eRmYmXOEY66jM7mJ7LzfsA=="], @@ -4282,12 +4319,14 @@ "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/pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "concurrently/yargs/cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + + "concurrently/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], "drizzle-kit/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.19.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA=="], @@ -4574,6 +4613,14 @@ "babel-plugin-module-resolver/glob/path-scurry/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "concurrently/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "concurrently/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "concurrently/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "concurrently/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "esbuild-plugin-copy/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "giget/tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], @@ -4584,6 +4631,8 @@ "nitropack/serve-static/send/fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="], + "nitropack/serve-static/send/statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], + "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.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.0", "http-errors": "^2.0.0", "iconv-lite": "^0.6.3", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.0", "type-is": "^2.0.0" } }, "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg=="], @@ -4604,6 +4653,8 @@ "opencontrol/@modelcontextprotocol/sdk/express/serve-static": ["serve-static@2.2.0", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ=="], + "opencontrol/@modelcontextprotocol/sdk/express/statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], + "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=="], "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=="], @@ -4632,6 +4683,10 @@ "@solidjs/start/shiki/@shikijs/engine-javascript/oniguruma-to-es/regex-recursion": ["regex-recursion@5.1.1", "", { "dependencies": { "regex": "^5.1.1", "regex-utilities": "^2.3.0" } }, "sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w=="], + "concurrently/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "concurrently/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "nitropack/c12/giget/nypm/tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], "opencontrol/@modelcontextprotocol/sdk/express/accepts/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], diff --git a/packages/desktop/.claude/settings.local.json b/packages/desktop/.claude/settings.local.json new file mode 100644 index 0000000000..3d49709307 --- /dev/null +++ b/packages/desktop/.claude/settings.local.json @@ -0,0 +1,29 @@ +{ + "permissions": { + "allow": [ + "Bash(npm run build)", + "Bash(opencode serve --help)", + "Read(//Users/jkneen/Documents/GitHub/flows/opencode-stt/packages/opencode/src/cli/cmd/**)", + "Read(//Users/jkneen/Documents/GitHub/flows/opencode-stt/packages/sdk/js/src/**)", + "Read(//Users/jkneen/Documents/GitHub/flows/opencode-stt/**)", + "Bash(curl -s http://localhost:4096)", + "Bash(curl -s http://localhost:4096/api/health)", + "Bash(curl -s http://localhost:4096/health)", + "Bash(lsof -i :4096)", + "Bash(curl -s http://localhost:4096/api/v1/session)", + "Bash(curl -v http://localhost:4096/v1/session)", + "Bash(curl -s http://localhost:4096/session)", + "Bash(curl -s http://localhost:4096/config)", + "Bash(curl -s \"http://localhost:4096/session?directory=/Users/jkneen/Documents/GitHub/flows/opencode-stt/packages/desktop\")", + "Bash(curl -v http://localhost:4096/session)", + "mcp__playwright__browser_navigate", + "mcp__playwright__browser_console_messages", + "mcp__playwright__browser_snapshot", + "mcp__playwright__browser_wait_for", + "mcp__playwright__browser_take_screenshot", + "Bash(chmod +x /Users/jkneen/Documents/GitHub/flows/opencode-stt/packages/desktop/scripts/tauri-dev.sh)" + ], + "deny": [], + "ask": [] + } +} diff --git a/packages/desktop/.env.example b/packages/desktop/.env.example new file mode 100644 index 0000000000..51f351c901 --- /dev/null +++ b/packages/desktop/.env.example @@ -0,0 +1,7 @@ +# OpenCode Server Configuration (not used when proxy is enabled) +VITE_OPENCODE_SERVER_HOST=127.0.0.1 +VITE_OPENCODE_SERVER_PORT=4096 + +# Vite Dev Server +PORT=5173 +HOST=127.0.0.1 diff --git a/packages/desktop/.playwright-mcp/desktop-ui-loaded.png b/packages/desktop/.playwright-mcp/desktop-ui-loaded.png new file mode 100644 index 0000000000..47cfc0049f Binary files /dev/null and b/packages/desktop/.playwright-mcp/desktop-ui-loaded.png differ diff --git a/packages/desktop/AGENTS.md b/packages/desktop/AGENTS.md index 3137bddc25..d20a72ffbd 100644 --- a/packages/desktop/AGENTS.md +++ b/packages/desktop/AGENTS.md @@ -2,10 +2,24 @@ ## Build/Test Commands -- **Development**: `bun run dev` (starts Vite dev server on port 3000) -- **Build**: `bun run build` (production build) -- **Preview**: `bun run serve` (preview production build) +### Development + +- **Web Dev**: `bun run dev` (starts Vite dev server on port 3000, responsive mobile UI at < 768px) +- **macOS Desktop**: `bun run tauri:dev` or `cargo tauri dev` +- **iOS Simulator**: `bun run ios:dev` or `cargo tauri ios dev "iPhone 16 Pro"` - **Validation**: Use `bun run typecheck` only - do not build or run project for validation + +### Production Builds + +- **Build All**: `./scripts/build-all.sh` (builds web, macOS desktop, and iOS) +- **Web Only**: `bun run build` (production web build) +- **macOS Desktop**: `bun run build:macos` (creates .app and .dmg) +- **iOS for Mac**: `bun run build:ios` (creates IPA that runs on iPhone, iPad, and Apple Silicon Macs) +- **iOS Simulator**: `bun run build:ios-sim` (for testing in simulator) + +### Testing + +- **Preview**: `bun run serve` (preview production build) - **Testing**: Do not create or run automated tests ## Code Style diff --git a/packages/desktop/BUILD.md b/packages/desktop/BUILD.md new file mode 100644 index 0000000000..253aaf6b79 --- /dev/null +++ b/packages/desktop/BUILD.md @@ -0,0 +1,150 @@ +# OpenCode Desktop - Build Guide + +## Platform Overview + +OpenCode Desktop can be built for three platforms: + +1. **macOS Desktop** - Traditional macOS app with desktop UI +2. **iOS** - iPhone and iPad app with mobile UI +3. **iOS on Mac** - iOS app running natively on Apple Silicon Macs with mobile UI + +## Prerequisites + +- macOS with Xcode installed +- Rust and Cargo +- Bun package manager +- Tauri CLI with iOS support +- Apple Developer account (for iOS builds) + +## Development + +### macOS Desktop + +```bash +bun run tauri:dev +# or +cargo tauri dev +``` + +### iOS Simulator + +```bash +bun run ios:dev +# or +cargo tauri ios dev "iPhone 16 Pro" +``` + +### Web (responsive mobile) + +```bash +bun dev +# Open http://localhost:3000 and resize window < 768px +``` + +## Building + +### Build All Platforms + +```bash +./scripts/build-all.sh +``` + +### Build Individual Platforms + +#### macOS Desktop + +```bash +bun run build:macos +# Creates: src-tauri/target/release/bundle/macos/OpenCode Desktop.app +# Creates: src-tauri/target/release/bundle/dmg/OpenCode Desktop_*.dmg +``` + +#### iOS (for iPhone, iPad, and Apple Silicon Macs) + +```bash +bun run build:ios +# Creates: src-tauri/gen/apple/build/arm64/Release-iphoneos/app_iOS.ipa +``` + +#### iOS Simulator Build + +```bash +bun run build:ios-sim +# Creates: src-tauri/gen/apple/build/arm64/Release-iphonesimulator/ +``` + +## Outputs + +### macOS Desktop + +- **Location**: `src-tauri/target/release/bundle/macos/` +- **Format**: `.app` bundle and `.dmg` installer +- **UI**: Desktop layout with resizable panes +- **Runs on**: Intel and Apple Silicon Macs + +### iOS App + +- **Location**: `src-tauri/gen/apple/build/arm64/Release-iphoneos/` +- **Format**: `.ipa` package +- **UI**: Mobile layout with bottom navigation +- **Runs on**: + - iPhone (iOS 14+) + - iPad (iOS 14+) + - Apple Silicon Macs (M1/M2/M3/M4) via "Designed for iPad" + +## Configuration + +### macOS Desktop + +- Config: `src-tauri/tauri.conf.json` +- Bundle ID: `ai.opencode.desktop` + +### iOS + +- Config: `src-tauri/tauri.ios.conf.json` (overrides) +- Xcode Project: `src-tauri/gen/apple/app.xcodeproj` +- Bundle ID: `ai.opencode.desktop` +- Development Team: `SW75ZJJ5R6` + +## Mac Catalyst / Designed for iPad + +The iOS build is configured to run on Apple Silicon Macs via "Designed for iPad" mode: + +- **SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD**: Enabled +- **UIDeviceFamily**: `[1, 2, 6]` (iPhone, iPad, Mac) +- **TARGETED_DEVICE_FAMILY**: `"1,2,6"` + +This allows the iOS app to be installed and run natively on M1+ Macs while showing the mobile UI. + +## Testing + +### Test iOS app on Mac + +1. Build iOS: `bun run build:ios` +2. Install the IPA on your Apple Silicon Mac +3. The app will run with the mobile UI (bottom navigation, drawer menu, etc.) + +### Test responsive web version + +1. Run: `bun dev` +2. Open browser to `http://localhost:3000` +3. Resize window to < 768px width +4. Mobile UI should activate automatically + +## Distribution + +### macOS Desktop + +- Use the `.dmg` for distribution +- Can be signed and notarized for distribution outside App Store + +### iOS + +- Use `--export-method app-store-connect` for App Store +- Use `--export-method release-testing` for TestFlight +- The same build works on iPhone, iPad, and Mac + +```bash +# Build for App Store +cargo tauri ios build --export-method app-store-connect +``` diff --git a/packages/desktop/PLATFORMS.md b/packages/desktop/PLATFORMS.md new file mode 100644 index 0000000000..9101cc3d32 --- /dev/null +++ b/packages/desktop/PLATFORMS.md @@ -0,0 +1,122 @@ +# Platform Support + +OpenCode Desktop is a multi-platform application with different UI modes: + +## 🖥️ macOS Desktop + +- **UI**: Traditional desktop layout with resizable panes +- **Build**: `bun run build:macos` +- **Dev**: `bun run tauri:dev` +- **Output**: `.app` bundle and `.dmg` installer +- **Runs on**: Intel and Apple Silicon Macs + +## 📱 iOS Mobile + +- **UI**: Mobile-first layout with bottom navigation +- **Build**: `bun run build:ios` +- **Dev**: `bun run ios:dev` +- **Output**: `.ipa` package +- **Runs on**: + - iPhone (iOS 14+) + - iPad (iOS 14+) + - **Apple Silicon Macs (M1/M2/M3/M4)** ✨ + +## 🌐 Web (Responsive) + +- **UI**: Responsive - desktop layout on wide screens, mobile layout on narrow screens +- **Build**: `bun run build` +- **Dev**: `bun run dev` +- **Breakpoint**: 768px (mobile UI activates at < 768px width) +- **Runs on**: Any modern web browser + +## Key Features by Platform + +| Feature | macOS Desktop | iOS | Web | +| ------------------ | ------------- | -------------- | ------------ | +| Resizable panes | ✅ | ❌ | ✅ | +| Bottom navigation | ❌ | ✅ | ✅ (< 768px) | +| Swipe gestures | ❌ | ✅ | ✅ (< 768px) | +| Drawer menu | ❌ | ✅ | ✅ (< 768px) | +| Keyboard shortcuts | ✅ | ⚠️ (limited) | ✅ | +| Haptic feedback | ❌ | ✅ | ❌ | +| File system access | ✅ (native) | ⚠️ (sandboxed) | ⚠️ (limited) | + +## iOS on Apple Silicon Macs + +The iOS build runs natively on Apple Silicon Macs using "Designed for iPad" mode: + +- Shows mobile UI (bottom nav, drawer, suggestion chips) +- Runs as native app (not browser-based) +- Installed from `.ipa` file +- Uses mobile-optimized layout and interactions +- Same binary as iPhone/iPad version + +**To install on Mac:** + +1. Build: `bun run build:ios` +2. Locate IPA: `src-tauri/gen/apple/build/arm64/Release-iphoneos/app_iOS.ipa` +3. Install via Finder or Apple Configurator +4. App appears in Launchpad/Applications + +## Development Workflow + +### Testing Mobile UI + +1. **iOS Simulator**: Most accurate for iOS-specific features + + ```bash + bun run ios:dev + ``` + +2. **Browser (Responsive)**: Fastest for iteration + + ```bash + bun dev + # Resize window to < 768px + ``` + +3. **Apple Silicon Mac**: Test final iOS build on Mac + ```bash + bun run build:ios + # Install IPA on Mac + ``` + +### Testing Desktop UI + +1. **macOS Native**: + + ```bash + bun run tauri:dev + ``` + +2. **Browser (Wide)**: + ```bash + bun dev + # Keep window > 768px + ``` + +## Build Automation + +Build all platforms at once: + +```bash +./scripts/build-all.sh +``` + +Outputs: + +- `src-tauri/target/release/bundle/macos/` - macOS desktop +- `src-tauri/target/release/bundle/dmg/` - macOS installer +- `src-tauri/gen/apple/build/arm64/Release-iphoneos/` - iOS app + +## Mobile UI Components + +The mobile UI includes these custom components: + +- `MobileLayout` - Single-pane navigation with tabs +- `MobileNavigation` - Bottom tab bar (Files/Editor/Chat) +- `MobileHeader` - Top header with title and menu button +- `Drawer` - Slide-out settings drawer +- `SuggestionChips` - Context-aware prompt suggestions + +Mobile detection is reactive and responds to window resizing in real-time. diff --git a/packages/desktop/README.md b/packages/desktop/README.md index 6a17645366..08b49fdaf8 100644 --- a/packages/desktop/README.md +++ b/packages/desktop/README.md @@ -10,14 +10,46 @@ $ npm install # or pnpm install or yarn install ### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs) +## Development + +### Web Development (Browser) +Run backend + Vite dev server: +```bash +npm run dev:web +``` +Then open: `http://127.0.0.1:5173/?directory=/Users/jkneen/Documents/GitHub/flows/opencode-stt/packages/desktop` + +### Desktop Development (Tauri Native App) +Run backend + Vite + Tauri: +```bash +npm start +# or +npm run dev:tauri +``` + +### Services Architecture + +The desktop app requires: +1. **OpenCode Backend** (`127.0.0.1:4096`) - API server +2. **Vite Dev Server** (`127.0.0.1:5173`) - UI with proxy to backend +3. **Tauri** - Native app wrapper (optional for browser-only dev) + +**Important:** All services use `127.0.0.1` (not `localhost`) to avoid IPv4/IPv6 networking issues. + +The startup scripts handle this automatically: +- `npm run dev:web` - Backend + Vite (browser testing) +- `npm start` - Backend + Vite + Tauri (native app) + ## Available Scripts -In the project directory, you can run: +### `npm start` or `npm run dev:tauri` + +Runs the Tauri native desktop app with backend and Vite dev server. -### `npm run dev` or `npm start` +### `npm run dev:web` -Runs the app in the development mode.
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser. +Runs backend + Vite for browser-based development.
+Open [http://127.0.0.1:5173/?directory=/path/to/project](http://127.0.0.1:5173/?directory=/path/to/project) The page will reload if you make edits.
diff --git a/packages/desktop/index.html b/packages/desktop/index.html index 1ee727ff41..b742f223d2 100644 --- a/packages/desktop/index.html +++ b/packages/desktop/index.html @@ -2,8 +2,13 @@ - + + + opencode diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 45acb25382..4f5a40a44a 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,26 +1,41 @@ { "name": "@opencode-ai/desktop", - "version": "0.15.4", + "version": "0.14.7", "description": "", "type": "module", "scripts": { - "start": "vite", + "start": "tauri dev", "dev": "vite", + "dev:web": "./scripts/dev.sh", + "dev:tauri": "tauri dev", + "serve": "./scripts/dev.sh", + "dev:backend": "opencode serve -p 4096 -h 127.0.0.1", "build": "vite build", - "serve": "vite preview", - "typecheck": "tsgo --noEmit" + "build:all": "npm run build && npm run build:tauri", + "build:tauri": "tauri build", + "build:macos": "tauri build --bundles app,dmg", + "build:ios": "tauri ios build --target aarch64", + "build:ios-sim": "tauri ios build --target aarch64-sim", + "preview": "vite preview", + "typecheck": "tsc --noEmit", + "tauri": "tauri", + "tauri:dev": "tauri dev", + "tauri:build": "tauri build", + "ios:dev": "tauri ios dev" }, "license": "MIT", "devDependencies": { - "@tailwindcss/vite": "catalog:", + "@tailwindcss/vite": "4.1.11", + "@tauri-apps/api": "2.8.0", + "@tauri-apps/cli": "2.8.4", "@tsconfig/bun": "1.0.9", "@types/luxon": "3.7.1", "@types/node": "catalog:", + "concurrently": "^9.1.2", "typescript": "catalog:", - "@typescript/native-preview": "catalog:", - "vite": "catalog:", + "vite": "^6.0.0", "vite-plugin-icons-spritesheet": "3.0.1", - "vite-plugin-solid": "catalog:" + "vite-plugin-solid": "^2.11.6" }, "dependencies": { "@kobalte/core": "catalog:", @@ -31,8 +46,7 @@ "@solid-primitives/scroll": "2.1.3", "@solidjs/router": "0.15.3", "@thisbeyond/solid-dnd": "0.7.5", - "diff": "catalog:", - "@opencode-ai/ui": "workspace:*", + "diff": "8.0.2", "fuzzysort": "catalog:", "luxon": "catalog:", "marked": "16.2.0", @@ -41,7 +55,7 @@ "solid-js": "catalog:", "shiki": "3.9.2", "solid-list": "0.3.0", - "tailwindcss": "catalog:", + "tailwindcss": "4.1.11", "virtua": "0.42.3" }, "prettier": { diff --git a/packages/desktop/scripts/build-all.sh b/packages/desktop/scripts/build-all.sh new file mode 100755 index 0000000000..5e214e7121 --- /dev/null +++ b/packages/desktop/scripts/build-all.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -e + +echo "🔨 Building OpenCode for all platforms..." + +# Build web assets +echo "📦 Building web assets..." +bun run build + +# Build macOS desktop app +echo "🍎 Building macOS desktop app..." +cargo tauri build --bundles app,dmg + +# Build iOS app (runs on iPhone, iPad, and Apple Silicon Macs) +echo "📱 Building iOS app for Apple Silicon Macs..." +cargo tauri ios build --target aarch64 + +echo "✅ All builds complete!" +echo "" +echo "Outputs:" +echo " macOS Desktop: src-tauri/target/release/bundle/macos/" +echo " iOS (Mac): src-tauri/gen/apple/build/arm64/Release-iphoneos/" diff --git a/packages/desktop/scripts/dev.sh b/packages/desktop/scripts/dev.sh new file mode 100755 index 0000000000..721e425a54 --- /dev/null +++ b/packages/desktop/scripts/dev.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +# OpenCode Desktop Development Launcher +# Starts API, Web, and Desktop app + +set -e + +# Colors +BLUE='\033[0;34m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +# Check if Backend is running +check_backend() { + curl -s http://127.0.0.1:4096 > /dev/null 2>&1 + return $? +} + +# Start OpenCode Backend Server +start_backend() { + export OPENCODE_PORT=4096 + echo -e "${BLUE}[BACKEND]${NC} Starting OpenCode backend server on 127.0.0.1:4096..." + if command -v opencode &> /dev/null; then + opencode serve -p 4096 -h 127.0.0.1 & + BACKEND_PID=$! + echo -e "${BLUE}[BACKEND]${NC} Started (PID: $BACKEND_PID)" + sleep 2 + else + echo -e "${RED}[BACKEND]${NC} opencode CLI not found. Install with: npm install -g @opencode-ai/cli" + exit 1 + fi +} + +# Start Web Frontend +start_web() { + echo -e "${GREEN}[WEB]${NC} Starting web frontend..." + # Web frontend is served by the desktop app's Vite dev server + # This will be available at the desktop app's URL + echo -e "${GREEN}[WEB]${NC} Web frontend will be served by desktop app" +} + +# Start Desktop +start_desktop() { + echo -e "${YELLOW}[DESKTOP]${NC} Starting desktop app..." + npm run dev & + DESKTOP_PID=$! + echo -e "${YELLOW}[DESKTOP]${NC} Started (PID: $DESKTOP_PID)" +} + +# Cleanup on exit +cleanup() { + echo "" + echo -e "${RED}Shutting down...${NC}" + [ ! -z "$BACKEND_PID" ] && kill $BACKEND_PID 2>/dev/null && echo -e "${BLUE}[BACKEND]${NC} Stopped" + [ ! -z "$DESKTOP_PID" ] && kill $DESKTOP_PID 2>/dev/null && echo -e "${YELLOW}[DESKTOP]${NC} Stopped" + exit 0 +} + +trap cleanup INT TERM + +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN} OpenCode Development Environment${NC}" +echo -e "${GREEN}========================================${NC}" +echo "" + +# Start backend server FIRST +if check_backend; then + echo -e "${BLUE}[BACKEND]${NC} Already running ✓" +else + start_backend + sleep 3 +fi + +# Then start desktop and web +start_desktop +sleep 2 + +# Web frontend is served by desktop app +start_web + +echo "" +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN} All services started!${NC}" +echo -e "${GREEN}========================================${NC}" +echo "" +echo -e "Desktop App: ${YELLOW}http://127.0.0.1:5173${NC}" +echo -e "Backend API: ${BLUE}http://127.0.0.1:4096${NC}" +echo "" +echo -e "Press ${RED}Ctrl+C${NC} to stop all services" +echo "" + +# Wait for all background processes +wait diff --git a/packages/desktop/scripts/tauri-dev.sh b/packages/desktop/scripts/tauri-dev.sh new file mode 100755 index 0000000000..355ad25a7b --- /dev/null +++ b/packages/desktop/scripts/tauri-dev.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Tauri Development Launcher +# Starts Backend then Vite for Tauri + +set -e + +# Colors +BLUE='\033[0;34m' +GREEN='\033[0;32m' +NC='\033[0m' # No Color + +# Check if Backend is running +check_backend() { + curl -s http://127.0.0.1:4096 > /dev/null 2>&1 + return $? +} + +# Start OpenCode Backend Server +start_backend() { + export OPENCODE_PORT=4096 + echo -e "${BLUE}[BACKEND]${NC} Starting OpenCode backend server on 127.0.0.1:4096..." + if command -v opencode &> /dev/null; then + opencode serve -p 4096 -h 127.0.0.1 & + BACKEND_PID=$! + echo -e "${BLUE}[BACKEND]${NC} Started (PID: $BACKEND_PID)" + sleep 3 + else + echo -e "${GREEN}[BACKEND]${NC} opencode CLI not found - Tauri will run without backend" + fi +} + +# Cleanup on exit +cleanup() { + [ ! -z "$BACKEND_PID" ] && kill $BACKEND_PID 2>/dev/null && echo -e "${BLUE}[BACKEND]${NC} Stopped" + exit 0 +} + +trap cleanup INT TERM + +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN} OpenCode Tauri Development${NC}" +echo -e "${GREEN}========================================${NC}" +echo "" + +# Start backend server if not already running +if check_backend; then + echo -e "${BLUE}[BACKEND]${NC} Already running ✓" +else + start_backend +fi + +echo -e "${GREEN}[VITE]${NC} Starting Vite dev server..." +echo "" + +# Start Vite (Tauri will handle this) +exec bun dev diff --git a/packages/desktop/src-tauri/.gitignore b/packages/desktop/src-tauri/.gitignore new file mode 100644 index 0000000000..502406b4ed --- /dev/null +++ b/packages/desktop/src-tauri/.gitignore @@ -0,0 +1,4 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ +/gen/schemas diff --git a/packages/desktop/src-tauri/AGENTS.md b/packages/desktop/src-tauri/AGENTS.md new file mode 100644 index 0000000000..2dadcb50db --- /dev/null +++ b/packages/desktop/src-tauri/AGENTS.md @@ -0,0 +1,42 @@ +# Agent Guidelines for @opencode/desktop + +## Build/Test Commands + +### Development + +- **Web Dev**: `bun run dev` (starts Vite dev server on port 3000, responsive mobile UI at < 768px) +- **macOS Desktop**: `bun run tauri:dev` or `cargo tauri dev` +- **iOS Simulator**: `bun run ios:dev` or `cargo tauri ios dev "iPhone 16 Pro"` +- **Validation**: Use `bun run typecheck` only - do not build or run project for validation + +### Production Builds + +- **Build All**: `./scripts/build-all.sh` (builds web, macOS desktop, and iOS) +- **Web Only**: `bun run build` (production web build) +- **macOS Desktop**: `bun run build:macos` (creates .app and .dmg) +- **iOS for Mac**: `bun run build:ios` (creates IPA that runs on iPhone, iPad, and Apple Silicon Macs) +- **iOS Simulator**: `bun run build:ios-sim` (for testing in simulator) + +### Testing + +- **Preview**: `bun run serve` (preview production build) +- **Testing**: Do not create or run automated tests + +## Code Style + +- **Framework**: SolidJS with TypeScript +- **Imports**: Use `@/` alias for src/ directory (e.g., `import Button from "@/ui/button"`) +- **Formatting**: Prettier configured with semicolons disabled, 120 character line width +- **Components**: Use function declarations, splitProps for component props +- **Types**: Define interfaces for component props, avoid `any` type +- **CSS**: TailwindCSS with custom CSS variables theme system +- **Naming**: PascalCase for components, camelCase for variables/functions, snake_case for file names +- **File Structure**: UI primitives in `/ui/`, higher-level components in `/components/`, pages in `/pages/`, providers in `/providers/` + +## Key Dependencies + +- SolidJS, @solidjs/router, @kobalte/core (UI primitives) +- TailwindCSS 4.x with @tailwindcss/vite +- Custom theme system with CSS variables +- Tauri for desktop app framework +- Rust backend with Cargo.toml configuration diff --git a/packages/desktop/src-tauri/Cargo.lock b/packages/desktop/src-tauri/Cargo.lock new file mode 100644 index 0000000000..7ceb8514a6 --- /dev/null +++ b/packages/desktop/src-tauri/Cargo.lock @@ -0,0 +1,5763 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.16", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "android_log-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" + +[[package]] +name = "android_logger" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" +dependencies = [ + "android_log-sys", + "env_filter", + "log", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "app" +version = "0.1.0" +dependencies = [ + "log", + "rfd", + "serde", + "serde_json", + "tauri", + "tauri-build", + "tauri-plugin-log", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ashpd" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cbdf310d77fd3aaee6ea2093db7011dc2d35d2eb3481e5607f1f8d942ed99df" +dependencies = [ + "async-fs", + "async-net", + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.9.2", + "raw-window-handle", + "serde", + "serde_repr", + "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "async-signal" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "atk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" +dependencies = [ + "atk-sys", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link 0.2.1", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +dependencies = [ + "serde", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2 0.6.3", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "borsh" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" +dependencies = [ + "borsh-derive", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3" +dependencies = [ + "once_cell", + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "brotli" +version = "8.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "byte-unit" +version = "5.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cd29c3c585209b0cbc7309bfe3ed7efd8c84c21b7af29c8bfae908f8777174" +dependencies = [ + "rust_decimal", + "serde", + "utf8-width", +] + +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bytemuck" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +dependencies = [ + "serde", +] + +[[package]] +name = "cairo-rs" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +dependencies = [ + "bitflags 2.9.4", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror 1.0.69", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "camino" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.17", +] + +[[package]] +name = "cargo_toml" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77" +dependencies = [ + "serde", + "toml 0.9.7", +] + +[[package]] +name = "cc" +version = "1.2.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d05d92f4b1fd76aad469d46cdd858ca761576082cd37df81416691e50199fb" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfb" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" +dependencies = [ + "byteorder", + "fnv", + "uuid", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link 0.2.1", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cookie" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "time", + "version_check", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.9.4", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.9.4", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cssparser" +version = "0.29.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "matches", + "phf 0.10.1", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.106", +] + +[[package]] +name = "ctor" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +dependencies = [ + "quote", + "syn 2.0.106", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.106", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "deranged" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" +dependencies = [ + "powerfmt", + "serde_core", +] + +[[package]] +name = "derive_more" +version = "0.99.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.106", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.9.4", + "block2 0.6.2", + "libc", + "objc2 0.6.3", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + +[[package]] +name = "dlopen2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b54f373ccf864bf587a89e880fb7610f8d73f3045f13580948ccbcaff26febff" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "788160fb30de9cdd857af31c6a2675904b16ece8fc2737b2c7127ba368c9d0f4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +dependencies = [ + "serde", +] + +[[package]] +name = "dtoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "embed-resource" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55a075fc573c64510038d7ee9abc7990635863992f83ebc52c8b433b8411a02e" +dependencies = [ + "cc", + "memchr", + "rustc_version", + "toml 0.9.7", + "vswhom", + "winreg", +] + +[[package]] +name = "embed_plist" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" + +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "erased-serde" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "fern" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" +dependencies = [ + "log", +] + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0399f9d26e5191ce32c498bebd31e7a3ceabc2745f0ac54af3f335126c3f24b3" + +[[package]] +name = "flate2" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "gdk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", + "once_cell", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkwayland-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "140071d506d223f7572b9f09b5e155afbd77428cd5cc7af8f2694c41d98dfe69" +dependencies = [ + "gdk-sys", + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkx11" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3caa00e14351bebbc8183b3c36690327eb77c49abc2268dd4bd36b856db3fbfe" +dependencies = [ + "gdk", + "gdkx11-sys", + "gio", + "glib", + "libc", + "x11", +] + +[[package]] +name = "gdkx11-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e7445fe01ac26f11601db260dd8608fe172514eb63b3b5e261ea6b0f4428d" +dependencies = [ + "gdk-sys", + "glib-sys", + "libc", + "system-deps", + "x11", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.7+wasi-0.2.4", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "gio" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.9.4", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "glib-macros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" +dependencies = [ + "heck 0.4.1", + "proc-macro-crate 2.0.2", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "glib-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "gobject-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" +dependencies = [ + "atk", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "html5ever" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" +dependencies = [ + "log", + "mac", + "markup5ever", + "match_token", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "http-range" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-util" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ico" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc50b891e4acf8fe0e71ef88ec43ad82ee07b3810ad09de10f1d01f072ed4b98" +dependencies = [ + "byteorder", + "png", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +dependencies = [ + "equivalent", + "hashbrown 0.16.0", + "serde", + "serde_core", +] + +[[package]] +name = "infer" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" +dependencies = [ + "cfb", +] + +[[package]] +name = "io-uring" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "libc", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "javascriptcore-rs" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" +dependencies = [ + "bitflags 1.3.2", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "js-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "json-patch" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "863726d7afb6bc2590eeff7135d923545e5e964f004c2ccf8716c25e70a86f08" +dependencies = [ + "jsonptr", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "jsonptr" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dea2b27dd239b2556ed7a25ba842fe47fd602e7fc7433c2a8d6106d4d9edd70" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "keyboard-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.9.4", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "kuchikiki" +version = "0.8.8-speedreader" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" +dependencies = [ + "cssparser", + "html5ever", + "indexmap 2.11.4", + "selectors", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libappindicator" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" +dependencies = [ + "gtk-sys", + "libloading", + "once_cell", +] + +[[package]] +name = "libc" +version = "0.2.176" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags 2.9.4", + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +dependencies = [ + "value-bag", +] + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" +dependencies = [ + "log", + "phf 0.11.3", + "phf_codegen 0.11.3", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "match_token" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +dependencies = [ + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", +] + +[[package]] +name = "muda" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "once_cell", + "png", + "serde", + "thiserror 2.0.17", + "windows-sys 0.60.2", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.9.4", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +dependencies = [ + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", + "objc2-exception-helper", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.9.4", + "block2 0.6.2", + "libc", + "objc2 0.6.3", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-text", + "objc2-core-video", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.9.4", + "dispatch2", + "objc2 0.6.3", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.9.4", + "dispatch2", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-core-video" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-io-surface", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-exception-helper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a" +dependencies = [ + "cc", +] + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.9.4", + "block2 0.5.1", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.9.4", + "block2 0.6.2", + "libc", + "objc2 0.6.3", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-javascript-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a1e6550c4caed348956ce3370c9ffeca70bb1dbed4fa96112e7c6170e074586" +dependencies = [ + "objc2 0.6.3", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.9.4", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.9.4", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-security" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-web-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" +dependencies = [ + "bitflags 2.9.4", + "block2 0.6.2", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-javascript-core", + "objc2-security", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "pango" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +dependencies = [ + "gio", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link 0.2.1", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_shared 0.8.0", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_macros 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros 0.11.3", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared 0.11.3", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher 1.0.1", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plist" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" +dependencies = [ + "base64 0.22.1", + "indexmap 2.11.4", + "quick-xml 0.38.3", + "serde", + "time", +] + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "potential_utf" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit 0.23.6", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "quick-xml" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.38.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.9.4", +] + +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 2.0.17", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "regex" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" + +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "reqwest" +version = "0.12.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + +[[package]] +name = "rfd" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2bee61e6cffa4635c72d7d81a84294e28f0930db0ddcb0f66d10244674ebed" +dependencies = [ + "ashpd", + "block2 0.6.2", + "dispatch2", + "js-sys", + "log", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "pollster", + "raw-window-handle", + "urlencoding", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rkyv" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rust_decimal" +version = "1.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8975fc98059f365204d635119cf9c5a60ae67b841ed49b5422a9a7e56cdfac0" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand 0.8.5", + "rkyv", + "serde", + "serde_json", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags 2.9.4", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +dependencies = [ + "dyn-clone", + "indexmap 1.9.3", + "schemars_derive", + "serde", + "serde_json", + "url", + "uuid", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.106", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "selectors" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" +dependencies = [ + "bitflags 1.3.2", + "cssparser", + "derive_more", + "fxhash", + "log", + "phf 0.8.0", + "phf_codegen 0.8.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-untagged" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" +dependencies = [ + "erased-serde", + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_spanned" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093cd8c01b25262b84927e0f7151692158fab02d961e04c979d3903eba7ecc5" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.11.4", + "schemars 0.9.0", + "schemars 1.0.4", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7e6c180db0816026a61afa1cff5344fb7ebded7e4d3062772179f2501481c27" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "serialize-to-javascript" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f3666a07a197cdb77cdf306c32be9b7f598d7060d50cfd4d5aa04bfd92f6c5" +dependencies = [ + "serde", + "serde_json", + "serialize-to-javascript-impl", +] + +[[package]] +name = "serialize-to-javascript-impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "servo_arc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +dependencies = [ + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "softbuffer" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" +dependencies = [ + "bytemuck", + "cfg_aliases", + "core-graphics", + "foreign-types", + "js-sys", + "log", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", + "raw-window-handle", + "redox_syscall", + "wasm-bindgen", + "web-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "soup3" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" +dependencies = [ + "futures-channel", + "gio", + "glib", + "libc", + "soup3-sys", +] + +[[package]] +name = "soup3-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.11.3", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "swift-rs" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4057c98e2e852d51fdcfca832aac7b571f6b351ad159f9eda5db1655f8d0c4d7" +dependencies = [ + "base64 0.21.7", + "serde", + "serde_json", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck 0.5.0", + "pkg-config", + "toml 0.8.2", + "version-compare", +] + +[[package]] +name = "tao" +version = "0.34.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "959469667dbcea91e5485fc48ba7dd6023face91bb0f1a14681a70f99847c3f7" +dependencies = [ + "bitflags 2.9.4", + "block2 0.6.2", + "core-foundation", + "core-graphics", + "crossbeam-channel", + "dispatch", + "dlopen2", + "dpi", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "jni", + "lazy_static", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-foundation 0.3.2", + "once_cell", + "parking_lot", + "raw-window-handle", + "scopeguard", + "tao-macros", + "unicode-segmentation", + "url", + "windows", + "windows-core 0.61.2", + "windows-version", + "x11-dl", +] + +[[package]] +name = "tao-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "tauri" +version = "2.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d1d3b3dc4c101ac989fd7db77e045cc6d91a25349cd410455cb5c57d510c1c" +dependencies = [ + "anyhow", + "bytes", + "cookie", + "dirs", + "dunce", + "embed_plist", + "getrandom 0.3.3", + "glob", + "gtk", + "heck 0.5.0", + "http", + "http-range", + "jni", + "libc", + "log", + "mime", + "muda", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-foundation 0.3.2", + "objc2-ui-kit", + "objc2-web-kit", + "percent-encoding", + "plist", + "raw-window-handle", + "reqwest", + "serde", + "serde_json", + "serde_repr", + "serialize-to-javascript", + "swift-rs", + "tauri-build", + "tauri-macros", + "tauri-runtime", + "tauri-runtime-wry", + "tauri-utils", + "thiserror 2.0.17", + "tokio", + "tray-icon", + "url", + "urlpattern", + "webkit2gtk", + "webview2-com", + "window-vibrancy", + "windows", +] + +[[package]] +name = "tauri-build" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c432ccc9ff661803dab74c6cd78de11026a578a9307610bbc39d3c55be7943f" +dependencies = [ + "anyhow", + "cargo_toml", + "dirs", + "glob", + "heck 0.5.0", + "json-patch", + "schemars 0.8.22", + "semver", + "serde", + "serde_json", + "tauri-utils", + "tauri-winres", + "toml 0.9.7", + "walkdir", +] + +[[package]] +name = "tauri-codegen" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab3a62cf2e6253936a8b267c2e95839674e7439f104fa96ad0025e149d54d8a" +dependencies = [ + "base64 0.22.1", + "brotli", + "ico", + "json-patch", + "plist", + "png", + "proc-macro2", + "quote", + "semver", + "serde", + "serde_json", + "sha2", + "syn 2.0.106", + "tauri-utils", + "thiserror 2.0.17", + "time", + "url", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4368ea8094e7045217edb690f493b55b30caf9f3e61f79b4c24b6db91f07995e" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.106", + "tauri-codegen", + "tauri-utils", +] + +[[package]] +name = "tauri-plugin" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9946a3cede302eac0c6eb6c6070ac47b1768e326092d32efbb91f21ed58d978f" +dependencies = [ + "anyhow", + "glob", + "plist", + "schemars 0.8.22", + "serde", + "serde_json", + "tauri-utils", + "toml 0.9.7", + "walkdir", +] + +[[package]] +name = "tauri-plugin-log" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c1438bc7662acd16d508c919b3c087efd63669a4c75625dff829b1c75975ec" +dependencies = [ + "android_logger", + "byte-unit", + "fern", + "log", + "objc2 0.6.3", + "objc2-foundation 0.3.2", + "serde", + "serde_json", + "serde_repr", + "swift-rs", + "tauri", + "tauri-plugin", + "thiserror 2.0.17", + "time", +] + +[[package]] +name = "tauri-runtime" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4cfc9ad45b487d3fded5a4731a567872a4812e9552e3964161b08edabf93846" +dependencies = [ + "cookie", + "dpi", + "gtk", + "http", + "jni", + "objc2 0.6.3", + "objc2-ui-kit", + "objc2-web-kit", + "raw-window-handle", + "serde", + "serde_json", + "tauri-utils", + "thiserror 2.0.17", + "url", + "webkit2gtk", + "webview2-com", + "windows", +] + +[[package]] +name = "tauri-runtime-wry" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fe9d48bd122ff002064e88cfcd7027090d789c4302714e68fcccba0f4b7807" +dependencies = [ + "gtk", + "http", + "jni", + "log", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-foundation 0.3.2", + "once_cell", + "percent-encoding", + "raw-window-handle", + "softbuffer", + "tao", + "tauri-runtime", + "tauri-utils", + "url", + "webkit2gtk", + "webview2-com", + "windows", + "wry", +] + +[[package]] +name = "tauri-utils" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a3852fdf9a4f8fbeaa63dc3e9a85284dd6ef7200751f0bd66ceee30c93f212" +dependencies = [ + "anyhow", + "brotli", + "cargo_metadata", + "ctor", + "dunce", + "glob", + "html5ever", + "http", + "infer", + "json-patch", + "kuchikiki", + "log", + "memchr", + "phf 0.11.3", + "proc-macro2", + "quote", + "regex", + "schemars 0.8.22", + "semver", + "serde", + "serde-untagged", + "serde_json", + "serde_with", + "swift-rs", + "thiserror 2.0.17", + "toml 0.9.7", + "url", + "urlpattern", + "uuid", + "walkdir", +] + +[[package]] +name = "tauri-winres" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd21509dd1fa9bd355dc29894a6ff10635880732396aa38c0066c1e6c1ab8074" +dependencies = [ + "embed-resource", + "toml 0.9.7", +] + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "time" +version = "0.3.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +dependencies = [ + "deranged", + "itoa", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + +[[package]] +name = "time-macros" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.47.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +dependencies = [ + "backtrace", + "bytes", + "io-uring", + "libc", + "mio", + "pin-project-lite", + "slab", + "socket2", + "windows-sys 0.59.0", +] + +[[package]] +name = "tokio-util" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "toml" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0" +dependencies = [ + "indexmap 2.11.4", + "serde_core", + "serde_spanned 1.0.2", + "toml_datetime 0.7.2", + "toml_parser", + "toml_writer", + "winnow 0.7.13", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.11.4", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.11.4", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.23.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3effe7c0e86fdff4f69cdd2ccc1b96f933e24811c5441d44904e8683e27184b" +dependencies = [ + "indexmap 2.11.4", + "toml_datetime 0.7.2", + "toml_parser", + "winnow 0.7.13", +] + +[[package]] +name = "toml_parser" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" +dependencies = [ + "winnow 0.7.13", +] + +[[package]] +name = "toml_writer" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109" + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.4", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tray-icon" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d92153331e7d02ec09137538996a7786fe679c629c279e82a6be762b7e6fe2" +dependencies = [ + "crossbeam-channel", + "dirs", + "libappindicator", + "muda", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", + "once_cell", + "png", + "serde", + "thiserror 2.0.17", + "windows-sys 0.59.0", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-ucd-ident" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "urlpattern" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d" +dependencies = [ + "regex", + "serde", + "unic-ucd-ident", + "url", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "getrandom 0.3.3", + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "value-bag" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" +dependencies = [ + "libc", + "vswhom-sys", +] + +[[package]] +name = "vswhom-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb067e4cbd1ff067d1df46c9194b5de0e98efd2810bbc95c5d5e5f25a3231150" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.106", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wayland-backend" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" +dependencies = [ + "cc", + "downcast-rs", + "rustix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" +dependencies = [ + "bitflags 2.9.4", + "rustix", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" +dependencies = [ + "bitflags 2.9.4", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" +dependencies = [ + "proc-macro2", + "quick-xml 0.37.5", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webkit2gtk" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup3", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" +dependencies = [ + "bitflags 1.3.2", + "cairo-sys-rs", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pkg-config", + "soup3-sys", + "system-deps", +] + +[[package]] +name = "webview2-com" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ba622a989277ef3886dd5afb3e280e3dd6d974b766118950a08f8f678ad6a4" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows", + "windows-core 0.61.2", + "windows-implement", + "windows-interface", +] + +[[package]] +name = "webview2-com-macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "webview2-com-sys" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c" +dependencies = [ + "thiserror 2.0.17", + "windows", + "windows-core 0.61.2", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "window-vibrancy" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c" +dependencies = [ + "objc2 0.6.3", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "raw-window-handle", + "windows-sys 0.59.0", + "windows-version", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-version" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.55.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" +dependencies = [ + "cfg-if", + "windows-sys 0.59.0", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "wry" +version = "0.53.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d78ec082b80fa088569a970d043bb3050abaabf4454101d44514ee8d9a8c9f6" +dependencies = [ + "base64 0.22.1", + "block2 0.6.2", + "cookie", + "crossbeam-channel", + "dirs", + "dpi", + "dunce", + "gdkx11", + "gtk", + "html5ever", + "http", + "javascriptcore-rs", + "jni", + "kuchikiki", + "libc", + "ndk", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-ui-kit", + "objc2-web-kit", + "once_cell", + "percent-encoding", + "raw-window-handle", + "sha2", + "soup3", + "tao-macros", + "thiserror 2.0.17", + "url", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows", + "windows-core 0.61.2", + "windows-version", + "x11-dl", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", +] + +[[package]] +name = "zbus" +version = "5.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d07e46d035fb8e375b2ce63ba4e4ff90a7f73cf2ffb0138b29e1158d2eaadf7" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "nix", + "ordered-stream", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "windows-sys 0.60.2", + "winnow 0.7.13", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e797a9c847ed3ccc5b6254e8bcce056494b375b511b3d6edcec0aeb4defaca" +dependencies = [ + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.106", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" +dependencies = [ + "serde", + "static_assertions", + "winnow 0.7.13", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "zvariant" +version = "5.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "999dd3be73c52b1fccd109a4a81e4fcd20fab1d3599c8121b38d04e1419498db" +dependencies = [ + "endi", + "enumflags2", + "serde", + "url", + "winnow 0.7.13", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6643fd0b26a46d226bd90d3f07c1b5321fe9bb7f04673cb37ac6d6883885b68e" +dependencies = [ + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.106", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6949d142f89f6916deca2232cf26a8afacf2b9fdc35ce766105e104478be599" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 2.0.106", + "winnow 0.7.13", +] diff --git a/packages/desktop/src-tauri/Cargo.toml b/packages/desktop/src-tauri/Cargo.toml new file mode 100644 index 0000000000..cecc9d753a --- /dev/null +++ b/packages/desktop/src-tauri/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "app" +version = "0.1.0" +description = "A Tauri App" +authors = ["you"] +license = "" +repository = "" +edition = "2021" +rust-version = "1.77.2" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "app_lib" +crate-type = ["staticlib", "cdylib", "rlib"] + +[build-dependencies] +tauri-build = { version = "2.4.1", features = [] } + +[dependencies] +serde_json = "1.0" +serde = { version = "1.0", features = ["derive"] } +log = "0.4" +tauri = { version = "2.8.5", features = ["protocol-asset"] } +tauri-plugin-log = "2" +rfd = "0.15" + +[package.metadata.bundle] +osx_info_plist_path = "Info.plist" diff --git a/packages/desktop/src-tauri/Info.plist b/packages/desktop/src-tauri/Info.plist new file mode 100644 index 0000000000..f4f4c073dd --- /dev/null +++ b/packages/desktop/src-tauri/Info.plist @@ -0,0 +1,8 @@ + + + + + NSMicrophoneUsageDescription + OpenCode needs microphone access for voice dictation + + diff --git a/packages/desktop/src-tauri/build.rs b/packages/desktop/src-tauri/build.rs new file mode 100644 index 0000000000..795b9b7c83 --- /dev/null +++ b/packages/desktop/src-tauri/build.rs @@ -0,0 +1,3 @@ +fn main() { + tauri_build::build() +} diff --git a/packages/desktop/src-tauri/capabilities/default.json b/packages/desktop/src-tauri/capabilities/default.json new file mode 100644 index 0000000000..c135d7f15d --- /dev/null +++ b/packages/desktop/src-tauri/capabilities/default.json @@ -0,0 +1,11 @@ +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "default", + "description": "enables the default permissions", + "windows": [ + "main" + ], + "permissions": [ + "core:default" + ] +} diff --git a/packages/desktop/src-tauri/gen/apple/.gitignore b/packages/desktop/src-tauri/gen/apple/.gitignore new file mode 100644 index 0000000000..6726e2f89b --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/.gitignore @@ -0,0 +1,3 @@ +xcuserdata/ +build/ +Externals/ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@1x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@1x.png new file mode 100644 index 0000000000..a6ac2a8ccf Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@1x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@2x-1.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@2x-1.png new file mode 100644 index 0000000000..2869541f73 Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@2x-1.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@2x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@2x.png new file mode 100644 index 0000000000..2869541f73 Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@2x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@3x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@3x.png new file mode 100644 index 0000000000..cf265a45d3 Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@3x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@1x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@1x.png new file mode 100644 index 0000000000..29c9746c05 Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@1x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@2x-1.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@2x-1.png new file mode 100644 index 0000000000..a4e68c8d6d Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@2x-1.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@2x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@2x.png new file mode 100644 index 0000000000..a4e68c8d6d Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@2x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@3x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@3x.png new file mode 100644 index 0000000000..e4adcbcedc Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@3x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@1x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@1x.png new file mode 100644 index 0000000000..2869541f73 Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@1x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@2x-1.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@2x-1.png new file mode 100644 index 0000000000..a414e65bb0 Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@2x-1.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@2x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@2x.png new file mode 100644 index 0000000000..a414e65bb0 Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@2x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@3x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@3x.png new file mode 100644 index 0000000000..a0807e5dfd Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@3x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png new file mode 100644 index 0000000000..704c929133 Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-60x60@2x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-60x60@2x.png new file mode 100644 index 0000000000..a0807e5dfd Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-60x60@2x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-60x60@3x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-60x60@3x.png new file mode 100644 index 0000000000..2a9fbc26ef Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-60x60@3x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-76x76@1x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-76x76@1x.png new file mode 100644 index 0000000000..2cdf18485f Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-76x76@1x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-76x76@2x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-76x76@2x.png new file mode 100644 index 0000000000..4723e4b45e Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-76x76@2x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5x83.5@2x.png b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5x83.5@2x.png new file mode 100644 index 0000000000..f26fee45c0 Binary files /dev/null and b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5x83.5@2x.png differ diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..90eea7ec7e --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "AppIcon-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "AppIcon-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "AppIcon-29x29@2x-1.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "AppIcon-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "AppIcon-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "AppIcon-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "AppIcon-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "AppIcon-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "AppIcon-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "AppIcon-20x20@2x-1.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "AppIcon-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "AppIcon-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "AppIcon-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "AppIcon-40x40@2x-1.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "AppIcon-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "AppIcon-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "AppIcon-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "AppIcon-512@2x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/packages/desktop/src-tauri/gen/apple/Assets.xcassets/Contents.json b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..da4a164c91 --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/packages/desktop/src-tauri/gen/apple/ExportOptions.plist b/packages/desktop/src-tauri/gen/apple/ExportOptions.plist new file mode 100644 index 0000000000..0428a171b3 --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/ExportOptions.plist @@ -0,0 +1,8 @@ + + + + + method + debugging + + diff --git a/packages/desktop/src-tauri/gen/apple/LaunchScreen.storyboard b/packages/desktop/src-tauri/gen/apple/LaunchScreen.storyboard new file mode 100644 index 0000000000..81b5f90e2f --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/LaunchScreen.storyboard @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/desktop/src-tauri/gen/apple/Podfile b/packages/desktop/src-tauri/gen/apple/Podfile new file mode 100644 index 0000000000..0fb99f08d7 --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/Podfile @@ -0,0 +1,21 @@ +# Uncomment the next line to define a global platform for your project + +target 'app_iOS' do +platform :ios, '14.0' + # Pods for app_iOS +end + +target 'app_macOS' do +platform :osx, '11.0' + # Pods for app_macOS +end + +# Delete the deployment target for iOS and macOS, causing it to be inherited from the Podfile +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET' + config.build_settings.delete 'MACOSX_DEPLOYMENT_TARGET' + end + end +end diff --git a/packages/desktop/src-tauri/gen/apple/Sources/app/bindings/bindings.h b/packages/desktop/src-tauri/gen/apple/Sources/app/bindings/bindings.h new file mode 100644 index 0000000000..51522007b6 --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/Sources/app/bindings/bindings.h @@ -0,0 +1,8 @@ +#pragma once + +namespace ffi { + extern "C" { + void start_app(); + } +} + diff --git a/packages/desktop/src-tauri/gen/apple/Sources/app/main.mm b/packages/desktop/src-tauri/gen/apple/Sources/app/main.mm new file mode 100644 index 0000000000..7793a9d5cf --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/Sources/app/main.mm @@ -0,0 +1,6 @@ +#include "bindings/bindings.h" + +int main(int argc, char * argv[]) { + ffi::start_app(); + return 0; +} diff --git a/packages/desktop/src-tauri/gen/apple/app.xcodeproj/project.pbxproj b/packages/desktop/src-tauri/gen/apple/app.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..ff0d564ee7 --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/app.xcodeproj/project.pbxproj @@ -0,0 +1,505 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 63; + objects = { + +/* Begin PBXBuildFile section */ + 299814393FFBF154FAD94CA8 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3673D372C5ABDD1AD6E7067 /* QuartzCore.framework */; }; + 3036F7131E55779ABF15BD58 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 02B7F8347F94B067E6B27396 /* LaunchScreen.storyboard */; }; + 31585529C029A01BE249A285 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E81BD6B453D87B7F7B1597B /* CoreGraphics.framework */; }; + 324A1E9A4258E7911D4DAC39 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9FACFFCB6E3743955F72464C /* Security.framework */; }; + 36C1893A7382FCD5A6A74845 /* libapp.a in Resources */ = {isa = PBXBuildFile; fileRef = CF674524E34966183631754E /* libapp.a */; }; + 53CDD0ACFBE8BDF1550B2E53 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 682535EEFE1DA20BE07B123C /* main.mm */; }; + 5C516481BCA83A182C2BCC94 /* assets in Resources */ = {isa = PBXBuildFile; fileRef = 3842AE2A64FB9933D0400EA4 /* assets */; }; + 618672DC8A5E0605441C9935 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E2B15F176E4B041AE33EEEA /* UIKit.framework */; }; + 836D84C5F07860664DAF79C8 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8F57162F5CC7AEDD55F173D /* WebKit.framework */; }; + 9D59FB167BB4E699DA17D1E9 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04B56F58E2E44DDE1D67E7B7 /* MetalKit.framework */; }; + C6BD59C055C986EA4A77FDA2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AF1DE57E7D9CF13BB2E0E038 /* Assets.xcassets */; }; + C869023DDFE275D42F3FBF29 /* libapp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 39EEC6A55698228E08917A52 /* libapp.a */; }; + E68F6CFDAED6503ABB4044A5 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE1209BFDECB28E00189B168 /* Metal.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 007E478DB8BC37A788C4730F /* app_iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = app_iOS.entitlements; sourceTree = ""; }; + 02B7F8347F94B067E6B27396 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; + 04B56F58E2E44DDE1D67E7B7 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; + 0E2B15F176E4B041AE33EEEA /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 1631E4CFBB715FFDBF919C8C /* main.rs */ = {isa = PBXFileReference; lastKnownFileType = text; path = main.rs; sourceTree = ""; }; + 17B52554D60D361AFE791C3E /* lib.rs */ = {isa = PBXFileReference; lastKnownFileType = text; path = lib.rs; sourceTree = ""; }; + 1E81BD6B453D87B7F7B1597B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 306B9C1792E7B1C53FA262A6 /* bindings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bindings.h; sourceTree = ""; }; + 3842AE2A64FB9933D0400EA4 /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; path = assets; sourceTree = SOURCE_ROOT; }; + 39EEC6A55698228E08917A52 /* libapp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libapp.a; sourceTree = ""; }; + 682535EEFE1DA20BE07B123C /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; + 81E326B61ED92E1D1EECF952 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 9FACFFCB6E3743955F72464C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + AF1DE57E7D9CF13BB2E0E038 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + CE1209BFDECB28E00189B168 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; + CF674524E34966183631754E /* libapp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libapp.a; sourceTree = ""; }; + D8F57162F5CC7AEDD55F173D /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + F3673D372C5ABDD1AD6E7067 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + FBC720DFA1D01F55B0A32344 /* OpenCode Desktop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "OpenCode Desktop.app"; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4825CF6C55516D374210C8E1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C869023DDFE275D42F3FBF29 /* libapp.a in Frameworks */, + 31585529C029A01BE249A285 /* CoreGraphics.framework in Frameworks */, + E68F6CFDAED6503ABB4044A5 /* Metal.framework in Frameworks */, + 9D59FB167BB4E699DA17D1E9 /* MetalKit.framework in Frameworks */, + 299814393FFBF154FAD94CA8 /* QuartzCore.framework in Frameworks */, + 324A1E9A4258E7911D4DAC39 /* Security.framework in Frameworks */, + 618672DC8A5E0605441C9935 /* UIKit.framework in Frameworks */, + 836D84C5F07860664DAF79C8 /* WebKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1BBF8C620E54F8C028CA130C /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1E81BD6B453D87B7F7B1597B /* CoreGraphics.framework */, + 39EEC6A55698228E08917A52 /* libapp.a */, + CE1209BFDECB28E00189B168 /* Metal.framework */, + 04B56F58E2E44DDE1D67E7B7 /* MetalKit.framework */, + F3673D372C5ABDD1AD6E7067 /* QuartzCore.framework */, + 9FACFFCB6E3743955F72464C /* Security.framework */, + 0E2B15F176E4B041AE33EEEA /* UIKit.framework */, + D8F57162F5CC7AEDD55F173D /* WebKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 2867E55E70187711EE923EBD /* app_iOS */ = { + isa = PBXGroup; + children = ( + 007E478DB8BC37A788C4730F /* app_iOS.entitlements */, + 81E326B61ED92E1D1EECF952 /* Info.plist */, + ); + path = app_iOS; + sourceTree = ""; + }; + 329C38BE5E8B40354375D0D0 /* bindings */ = { + isa = PBXGroup; + children = ( + 306B9C1792E7B1C53FA262A6 /* bindings.h */, + ); + path = bindings; + sourceTree = ""; + }; + 5F72359403FB561BE1489F63 /* debug */ = { + isa = PBXGroup; + children = ( + CF674524E34966183631754E /* libapp.a */, + ); + path = debug; + sourceTree = ""; + }; + 70DD658F1D4B0FED51A79854 /* arm64 */ = { + isa = PBXGroup; + children = ( + 5F72359403FB561BE1489F63 /* debug */, + ); + path = arm64; + sourceTree = ""; + }; + 78CBE3E5873199C0066F12DF /* Sources */ = { + isa = PBXGroup; + children = ( + FB1C68C0357A1866B3D27465 /* app */, + ); + path = Sources; + sourceTree = ""; + }; + 855775165ACE55D883F89EB3 /* src */ = { + isa = PBXGroup; + children = ( + 17B52554D60D361AFE791C3E /* lib.rs */, + 1631E4CFBB715FFDBF919C8C /* main.rs */, + ); + name = src; + path = ../../src; + sourceTree = ""; + }; + 87648061424F20D5D4871E9E = { + isa = PBXGroup; + children = ( + 3842AE2A64FB9933D0400EA4 /* assets */, + AF1DE57E7D9CF13BB2E0E038 /* Assets.xcassets */, + 02B7F8347F94B067E6B27396 /* LaunchScreen.storyboard */, + 2867E55E70187711EE923EBD /* app_iOS */, + BAFB695BB8415511FEC74542 /* Externals */, + 78CBE3E5873199C0066F12DF /* Sources */, + 855775165ACE55D883F89EB3 /* src */, + 1BBF8C620E54F8C028CA130C /* Frameworks */, + EE72B6AC647386A11F795E44 /* Products */, + ); + sourceTree = ""; + }; + BAFB695BB8415511FEC74542 /* Externals */ = { + isa = PBXGroup; + children = ( + 70DD658F1D4B0FED51A79854 /* arm64 */, + ); + path = Externals; + sourceTree = ""; + }; + EE72B6AC647386A11F795E44 /* Products */ = { + isa = PBXGroup; + children = ( + FBC720DFA1D01F55B0A32344 /* OpenCode Desktop.app */, + ); + name = Products; + sourceTree = ""; + }; + FB1C68C0357A1866B3D27465 /* app */ = { + isa = PBXGroup; + children = ( + 682535EEFE1DA20BE07B123C /* main.mm */, + 329C38BE5E8B40354375D0D0 /* bindings */, + ); + path = app; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + E86255CB8A1836C0BF0C0E14 /* app_iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = CDCB6DFA1AEBFEE3F608BA27 /* Build configuration list for PBXNativeTarget "app_iOS" */; + buildPhases = ( + E028F843270D8815FCE2B491 /* Build Rust Code */, + 81BE6BC5B603407AF570E994 /* Sources */, + 2FBCB8C3ED193E9C4A9FDB59 /* Resources */, + 4825CF6C55516D374210C8E1 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = app_iOS; + packageProductDependencies = ( + ); + productName = app_iOS; + productReference = FBC720DFA1D01F55B0A32344 /* OpenCode Desktop.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A9B1B09F1872768368ACECE2 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 2600; + }; + buildConfigurationList = B302E784349268C93E6F0A36 /* Build configuration list for PBXProject "app" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = 87648061424F20D5D4871E9E; + minimizedProjectReferenceProxies = 1; + projectDirPath = ""; + projectRoot = ""; + targets = ( + E86255CB8A1836C0BF0C0E14 /* app_iOS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2FBCB8C3ED193E9C4A9FDB59 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C6BD59C055C986EA4A77FDA2 /* Assets.xcassets in Resources */, + 3036F7131E55779ABF15BD58 /* LaunchScreen.storyboard in Resources */, + 5C516481BCA83A182C2BCC94 /* assets in Resources */, + 36C1893A7382FCD5A6A74845 /* libapp.a in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + E028F843270D8815FCE2B491 /* Build Rust Code */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Build Rust Code"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a", + "$(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export PATH=\"/Users/jkneen/.cargo/bin:$PATH\"\ncargo tauri ios xcode-script -v --platform ${PLATFORM_DISPLAY_NAME:?} --sdk-root ${SDKROOT:?} --framework-search-paths \"${FRAMEWORK_SEARCH_PATHS:?}\" --header-search-paths \"${HEADER_SEARCH_PATHS:?}\" --gcc-preprocessor-definitions \"${GCC_PREPROCESSOR_DEFINITIONS:-}\" --configuration ${CONFIGURATION:?} ${FORCE_COLOR} ${ARCHS:?}\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 81BE6BC5B603407AF570E994 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 53CDD0ACFBE8BDF1550B2E53 /* main.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1B9D5B8D34E6E0C88D0207F2 /* release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = app_iOS/app_iOS.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + ENABLE_BITCODE = NO; + "EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\".\"", + ); + INFOPLIST_FILE = app_iOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + "LIBRARY_SEARCH_PATHS[arch=arm64]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION)", + "$(SDKROOT)/usr/lib/swift", + "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", + "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", + ); + "LIBRARY_SEARCH_PATHS[arch=x86_64]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION)", + "$(SDKROOT)/usr/lib/swift", + "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", + "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", + ); + PRODUCT_BUNDLE_IDENTIFIER = ai.opencode.desktop; + PRODUCT_NAME = "OpenCode Desktop"; + SDKROOT = iphoneos; + SUPPORTS_MACCATALYST = YES; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; + TARGETED_DEVICE_FAMILY = "1,2,6"; + VALID_ARCHS = arm64; + DEVELOPMENT_TEAM = "SW75ZJJ5R6"; + }; + name = release; + }; + 3C6497CF9EADFA373F12EF5C /* release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = SW75ZJJ5R6; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + }; + name = release; + }; + 4AC19FD47C6011940ACEB467 /* debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = app_iOS/app_iOS.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + ENABLE_BITCODE = NO; + "EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\".\"", + ); + INFOPLIST_FILE = app_iOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + "LIBRARY_SEARCH_PATHS[arch=arm64]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION)", + "$(SDKROOT)/usr/lib/swift", + "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", + "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", + ); + "LIBRARY_SEARCH_PATHS[arch=x86_64]" = ( + "$(inherited)", + "$(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION)", + "$(SDKROOT)/usr/lib/swift", + "$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", + "$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)", + ); + PRODUCT_BUNDLE_IDENTIFIER = ai.opencode.desktop; + PRODUCT_NAME = "OpenCode Desktop"; + SDKROOT = iphoneos; + SUPPORTS_MACCATALYST = YES; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; + TARGETED_DEVICE_FAMILY = "1,2,6"; + VALID_ARCHS = arm64; + DEVELOPMENT_TEAM = "SW75ZJJ5R6"; + }; + name = debug; + }; + CAA806262C53A2E15E5DB0CA /* debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = SW75ZJJ5R6; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B302E784349268C93E6F0A36 /* Build configuration list for PBXProject "app" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CAA806262C53A2E15E5DB0CA /* debug */, + 3C6497CF9EADFA373F12EF5C /* release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = debug; + }; + CDCB6DFA1AEBFEE3F608BA27 /* Build configuration list for PBXNativeTarget "app_iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4AC19FD47C6011940ACEB467 /* debug */, + 1B9D5B8D34E6E0C88D0207F2 /* release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = A9B1B09F1872768368ACECE2 /* Project object */; +} diff --git a/packages/desktop/src-tauri/gen/apple/app.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/desktop/src-tauri/gen/apple/app.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..919434a625 --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/app.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/desktop/src-tauri/gen/apple/app.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/desktop/src-tauri/gen/apple/app.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000000..7f25aeeacd --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/app.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,10 @@ + + + + + BuildSystemType + Latest + DisableBuildSystemDeprecationDiagnostic + + + diff --git a/packages/desktop/src-tauri/gen/apple/app.xcodeproj/xcshareddata/xcschemes/app_iOS.xcscheme b/packages/desktop/src-tauri/gen/apple/app.xcodeproj/xcshareddata/xcschemes/app_iOS.xcscheme new file mode 100644 index 0000000000..eea080c37e --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/app.xcodeproj/xcshareddata/xcschemes/app_iOS.xcscheme @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/desktop/src-tauri/gen/apple/app_iOS/Info.plist b/packages/desktop/src-tauri/gen/apple/app_iOS/Info.plist new file mode 100644 index 0000000000..163ac82f79 --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/app_iOS/Info.plist @@ -0,0 +1,52 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.1.0 + CFBundleVersion + 0.1.0 + LSRequiresIPhoneOS + + UIDeviceFamily + + 1 + 2 + 6 + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + arm64 + metal + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + NSMicrophoneUsageDescription + OpenCode needs microphone access for voice dictation + + \ No newline at end of file diff --git a/packages/desktop/src-tauri/gen/apple/app_iOS/app_iOS.entitlements b/packages/desktop/src-tauri/gen/apple/app_iOS/app_iOS.entitlements new file mode 100644 index 0000000000..e89b7f323c --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/app_iOS/app_iOS.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/packages/desktop/src-tauri/gen/apple/project.yml b/packages/desktop/src-tauri/gen/apple/project.yml new file mode 100644 index 0000000000..ae1859bd21 --- /dev/null +++ b/packages/desktop/src-tauri/gen/apple/project.yml @@ -0,0 +1,94 @@ +name: app +options: + bundleIdPrefix: ai.opencode.desktop + deploymentTarget: + iOS: 14.0 +fileGroups: [../../src] +configs: + debug: debug + release: release +settingGroups: + app: + base: + PRODUCT_NAME: OpenCode Desktop + PRODUCT_BUNDLE_IDENTIFIER: ai.opencode.desktop +targetTemplates: + app: + type: application + sources: + - path: Sources + scheme: + environmentVariables: + RUST_BACKTRACE: full + RUST_LOG: info + settings: + groups: [app] +targets: + app_iOS: + type: application + platform: iOS + sources: + - path: Sources + - path: Assets.xcassets + - path: Externals + - path: app_iOS + - path: assets + buildPhase: resources + type: folder + - path: LaunchScreen.storyboard + info: + path: app_iOS/Info.plist + properties: + LSRequiresIPhoneOS: true + UILaunchStoryboardName: LaunchScreen + UIRequiredDeviceCapabilities: [arm64, metal] + UISupportedInterfaceOrientations: + - UIInterfaceOrientationPortrait + - UIInterfaceOrientationLandscapeLeft + - UIInterfaceOrientationLandscapeRight + UISupportedInterfaceOrientations~ipad: + - UIInterfaceOrientationPortrait + - UIInterfaceOrientationPortraitUpsideDown + - UIInterfaceOrientationLandscapeLeft + - UIInterfaceOrientationLandscapeRight + CFBundleShortVersionString: 0.1.0 + CFBundleVersion: "0.1.0" + UIDeviceFamily: [1, 2, 6] + entitlements: + path: app_iOS/app_iOS.entitlements + scheme: + environmentVariables: + RUST_BACKTRACE: full + RUST_LOG: info + settings: + base: + ENABLE_BITCODE: false + ARCHS: [arm64] + VALID_ARCHS: arm64 + LIBRARY_SEARCH_PATHS[arch=x86_64]: $(inherited) $(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) + LIBRARY_SEARCH_PATHS[arch=arm64]: $(inherited) $(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES: true + EXCLUDED_ARCHS[sdk=iphoneos*]: x86_64 + SUPPORTS_MACCATALYST: true + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD: true + TARGETED_DEVICE_FAMILY: "1,2,6" + groups: [app] + dependencies: + - framework: libapp.a + embed: false + - sdk: CoreGraphics.framework + - sdk: Metal.framework + - sdk: MetalKit.framework + - sdk: QuartzCore.framework + - sdk: Security.framework + - sdk: UIKit.framework + - sdk: WebKit.framework + preBuildScripts: + - script: | + export PATH="/Users/jkneen/.cargo/bin:$PATH" + cargo tauri ios xcode-script -v --platform ${PLATFORM_DISPLAY_NAME:?} --sdk-root ${SDKROOT:?} --framework-search-paths "${FRAMEWORK_SEARCH_PATHS:?}" --header-search-paths "${HEADER_SEARCH_PATHS:?}" --gcc-preprocessor-definitions "${GCC_PREPROCESSOR_DEFINITIONS:-}" --configuration ${CONFIGURATION:?} ${FORCE_COLOR} ${ARCHS:?} + name: Build Rust Code + basedOnDependencyAnalysis: false + outputFiles: + - $(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a + - $(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a diff --git a/packages/desktop/src-tauri/icons/128x128.png b/packages/desktop/src-tauri/icons/128x128.png new file mode 100644 index 0000000000..1f469abba7 Binary files /dev/null and b/packages/desktop/src-tauri/icons/128x128.png differ diff --git a/packages/desktop/src-tauri/icons/128x128@2x.png b/packages/desktop/src-tauri/icons/128x128@2x.png new file mode 100644 index 0000000000..785b9b9ac1 Binary files /dev/null and b/packages/desktop/src-tauri/icons/128x128@2x.png differ diff --git a/packages/desktop/src-tauri/icons/32x32.png b/packages/desktop/src-tauri/icons/32x32.png new file mode 100644 index 0000000000..15512351e3 Binary files /dev/null and b/packages/desktop/src-tauri/icons/32x32.png differ diff --git a/packages/desktop/src-tauri/icons/Square107x107Logo.png b/packages/desktop/src-tauri/icons/Square107x107Logo.png new file mode 100644 index 0000000000..f35d84ff13 Binary files /dev/null and b/packages/desktop/src-tauri/icons/Square107x107Logo.png differ diff --git a/packages/desktop/src-tauri/icons/Square142x142Logo.png b/packages/desktop/src-tauri/icons/Square142x142Logo.png new file mode 100644 index 0000000000..1823bb2696 Binary files /dev/null and b/packages/desktop/src-tauri/icons/Square142x142Logo.png differ diff --git a/packages/desktop/src-tauri/icons/Square150x150Logo.png b/packages/desktop/src-tauri/icons/Square150x150Logo.png new file mode 100644 index 0000000000..dc2b22cea5 Binary files /dev/null and b/packages/desktop/src-tauri/icons/Square150x150Logo.png differ diff --git a/packages/desktop/src-tauri/icons/Square284x284Logo.png b/packages/desktop/src-tauri/icons/Square284x284Logo.png new file mode 100644 index 0000000000..0ed3984c5f Binary files /dev/null and b/packages/desktop/src-tauri/icons/Square284x284Logo.png differ diff --git a/packages/desktop/src-tauri/icons/Square30x30Logo.png b/packages/desktop/src-tauri/icons/Square30x30Logo.png new file mode 100644 index 0000000000..60bf0eadf7 Binary files /dev/null and b/packages/desktop/src-tauri/icons/Square30x30Logo.png differ diff --git a/packages/desktop/src-tauri/icons/Square310x310Logo.png b/packages/desktop/src-tauri/icons/Square310x310Logo.png new file mode 100644 index 0000000000..c8ca0ad132 Binary files /dev/null and b/packages/desktop/src-tauri/icons/Square310x310Logo.png differ diff --git a/packages/desktop/src-tauri/icons/Square44x44Logo.png b/packages/desktop/src-tauri/icons/Square44x44Logo.png new file mode 100644 index 0000000000..8756459b63 Binary files /dev/null and b/packages/desktop/src-tauri/icons/Square44x44Logo.png differ diff --git a/packages/desktop/src-tauri/icons/Square71x71Logo.png b/packages/desktop/src-tauri/icons/Square71x71Logo.png new file mode 100644 index 0000000000..2c8023cc82 Binary files /dev/null and b/packages/desktop/src-tauri/icons/Square71x71Logo.png differ diff --git a/packages/desktop/src-tauri/icons/Square89x89Logo.png b/packages/desktop/src-tauri/icons/Square89x89Logo.png new file mode 100644 index 0000000000..2c5e6034ff Binary files /dev/null and b/packages/desktop/src-tauri/icons/Square89x89Logo.png differ diff --git a/packages/desktop/src-tauri/icons/StoreLogo.png b/packages/desktop/src-tauri/icons/StoreLogo.png new file mode 100644 index 0000000000..17d142c0a4 Binary files /dev/null and b/packages/desktop/src-tauri/icons/StoreLogo.png differ diff --git a/packages/desktop/src-tauri/icons/icon.icns b/packages/desktop/src-tauri/icons/icon.icns new file mode 100644 index 0000000000..53aa497cb8 Binary files /dev/null and b/packages/desktop/src-tauri/icons/icon.icns differ diff --git a/packages/desktop/src-tauri/icons/icon.ico b/packages/desktop/src-tauri/icons/icon.ico new file mode 100644 index 0000000000..06c23c82fe Binary files /dev/null and b/packages/desktop/src-tauri/icons/icon.ico differ diff --git a/packages/desktop/src-tauri/icons/icon.png b/packages/desktop/src-tauri/icons/icon.png new file mode 100644 index 0000000000..7e935121c6 Binary files /dev/null and b/packages/desktop/src-tauri/icons/icon.png differ diff --git a/packages/desktop/src-tauri/src/lib.rs b/packages/desktop/src-tauri/src/lib.rs new file mode 100644 index 0000000000..a8658967ee --- /dev/null +++ b/packages/desktop/src-tauri/src/lib.rs @@ -0,0 +1,173 @@ +use std::process::{Command, Stdio}; +use std::sync::Mutex; +use tauri::Manager; + +struct ServerState { + child: Option, + port: Option, +} + + + +fn get_opencode_path() -> Option { + let shell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/zsh".to_string()); + + let output = Command::new(&shell) + .arg("-l") + .arg("-c") + .arg("which opencode") + .output() + .ok()?; + + if output.status.success() { + String::from_utf8(output.stdout) + .ok() + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()) + } else { + None + } +} + +#[tauri::command] +fn check_opencode_installed() -> bool { + get_opencode_path().is_some() +} + +#[tauri::command] +fn start_opencode_server(state: tauri::State>) -> Result { + let mut server_state = state.lock().unwrap(); + + if let Some(port) = server_state.port { + return Ok(port); + } + + let opencode_path = get_opencode_path() + .ok_or_else(|| "OpenCode CLI not found in PATH".to_string())?; + + eprintln!("Found opencode at: {}", opencode_path); + + let port: u16 = 56849; + + eprintln!("Starting server on port: {}", port); + + let home_dir = std::env::var("HOME") + .map_err(|e| format!("Failed to get HOME: {}", e))?; + + let child = Command::new(&opencode_path) + .arg("serve") + .arg("--port") + .arg(port.to_string()) + .current_dir(&home_dir) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .map_err(|e| { + eprintln!("Failed to spawn: {}", e); + format!("Failed to start server: {}", e) + })?; + + eprintln!("Server process started with PID: {:?}", child.id()); + + server_state.child = Some(child); + server_state.port = Some(port); + + Ok(port) +} + +#[tauri::command] +fn get_git_branch(path: String) -> Result { + let output = Command::new("git") + .arg("-C") + .arg(&path) + .arg("rev-parse") + .arg("--abbrev-ref") + .arg("HEAD") + .output() + .map_err(|e| format!("Failed to get git branch: {}", e))?; + + if output.status.success() { + String::from_utf8(output.stdout) + .ok() + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()) + .ok_or_else(|| "No branch found".to_string()) + } else { + Err("Not a git repository".to_string()) + } +} + +#[tauri::command] +fn select_folder(state: tauri::State>) -> Result { + use rfd::FileDialog; + + let folder_path = FileDialog::new() + .set_title("Select Project Folder") + .pick_folder() + .ok_or_else(|| "No folder selected".to_string())? + .to_string_lossy() + .to_string(); + + eprintln!("Folder selected: {}", folder_path); + + let mut server_state = state.lock().unwrap(); + + if let Some(mut child) = server_state.child.take() { + eprintln!("Killing existing server process"); + let _ = child.kill(); + } + + let opencode_path = get_opencode_path() + .ok_or_else(|| "OpenCode CLI not found in PATH".to_string())?; + + let port: u16 = 56849; + + eprintln!("Starting server with path: {}", folder_path); + + let child = Command::new(&opencode_path) + .arg("serve") + .arg("--port") + .arg(port.to_string()) + .current_dir(&folder_path) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .map_err(|e| format!("Failed to start server: {}", e))?; + + eprintln!("Server restarted with PID: {:?}", child.id()); + + server_state.child = Some(child); + server_state.port = Some(port); + + Ok(folder_path) +} + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + tauri::Builder::default() + .manage(Mutex::new(ServerState { child: None, port: None })) + .invoke_handler(tauri::generate_handler![ + check_opencode_installed, + start_opencode_server, + select_folder, + get_git_branch + ]) + .setup(|app| { + if cfg!(debug_assertions) { + app.handle().plugin( + tauri_plugin_log::Builder::default() + .level(log::LevelFilter::Info) + .build(), + )?; + } + + let state = app.state::>(); + if let Err(e) = start_opencode_server(state) { + eprintln!("Warning: Failed to auto-start server: {}", e); + } + + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} diff --git a/packages/desktop/src-tauri/src/main.rs b/packages/desktop/src-tauri/src/main.rs new file mode 100644 index 0000000000..ad5fe83991 --- /dev/null +++ b/packages/desktop/src-tauri/src/main.rs @@ -0,0 +1,6 @@ +// Prevents additional console window on Windows in release, DO NOT REMOVE!! +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +fn main() { + app_lib::run(); +} diff --git a/packages/desktop/src-tauri/tauri.conf.json b/packages/desktop/src-tauri/tauri.conf.json new file mode 100644 index 0000000000..ed2b7d1bfb --- /dev/null +++ b/packages/desktop/src-tauri/tauri.conf.json @@ -0,0 +1,53 @@ +{ + "$schema": "../../../node_modules/@tauri-apps/cli/config.schema.json", + "productName": "OpenCode Desktop", + "version": "0.1.0", + "identifier": "ai.opencode.desktop", + "build": { + "frontendDist": "../dist", + "beforeDevCommand": "../scripts/tauri-dev.sh", + "beforeBuildCommand": "bun run build" + }, + "app": { + "windows": [ + { + "title": "@opencode-ai/desktop", + "width": 800, + "height": 600, + "resizable": true, + "fullscreen": false, + "devtools": true + } + ], + "security": { + "csp": null, + "assetProtocol": { + "enable": true, + "scope": ["**"] + } + }, + "withGlobalTauri": true + }, + "plugins": { + "fs": { + "scope": [ + "$RESOURCE/**", + "$APP/**", + "$APPDATA/**", + "$APPLOCALDATA/**", + "$APPLOG/**", + "$APPCONFIG/**", + "$APPCACHE/**", + "../gen/apple/**" + ] + } + }, + "bundle": { + "active": true, + "targets": "all", + "icon": ["icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"], + "iOS": { + "developmentTeam": "SW75ZJJ5R6" + } + } +} diff --git a/packages/desktop/src-tauri/tauri.ios.conf.json b/packages/desktop/src-tauri/tauri.ios.conf.json new file mode 100644 index 0000000000..9fc29131c4 --- /dev/null +++ b/packages/desktop/src-tauri/tauri.ios.conf.json @@ -0,0 +1,5 @@ +{ + "build": { + "beforeBuildCommand": "bun run build" + } +} diff --git a/packages/desktop/src/assets/theme.css b/packages/desktop/src/assets/theme.css new file mode 100644 index 0000000000..78673ecc09 --- /dev/null +++ b/packages/desktop/src/assets/theme.css @@ -0,0 +1,2386 @@ +/* Auto-generated theme CSS - Do not edit manually */ +:root { + --theme-primary: #3b7dd8; + --theme-secondary: #7b5bb6; + --theme-accent: #d68c27; + --theme-error: #d1383d; + --theme-warning: #d68c27; + --theme-success: #3d9a57; + --theme-info: #318795; + --theme-text: #1a1a1a; + --theme-text-muted: #8a8a8a; + --theme-background: #ffffff; + --theme-background-panel: #fafafa; + --theme-background-element: #f5f5f5; + --theme-border: #b8b8b8; + --theme-border-active: #a0a0a0; + --theme-border-subtle: #d4d4d4; + --theme-diff-added: #1e725c; + --theme-diff-removed: #c53b53; + --theme-diff-context: #7086b5; + --theme-diff-hunk-header: #7086b5; + --theme-diff-highlight-added: #4db380; + --theme-diff-highlight-removed: #f52a65; + --theme-diff-added-bg: #d5e5d5; + --theme-diff-removed-bg: #f7d8db; + --theme-diff-context-bg: #fafafa; + --theme-diff-line-number: #f5f5f5; + --theme-diff-added-line-number-bg: #c5d5c5; + --theme-diff-removed-line-number-bg: #e7c8cb; + --theme-markdown-text: #1a1a1a; + --theme-markdown-heading: #d68c27; + --theme-markdown-link: #3b7dd8; + --theme-markdown-link-text: #318795; + --theme-markdown-code: #3d9a57; + --theme-markdown-block-quote: #b0851f; + --theme-markdown-emph: #b0851f; + --theme-markdown-strong: #d68c27; + --theme-markdown-horizontal-rule: #8a8a8a; + --theme-markdown-list-item: #3b7dd8; + --theme-markdown-list-enumeration: #318795; + --theme-markdown-image: #3b7dd8; + --theme-markdown-image-text: #318795; + --theme-markdown-code-block: #1a1a1a; + --theme-syntax-comment: #8a8a8a; + --theme-syntax-keyword: #d68c27; + --theme-syntax-function: #3b7dd8; + --theme-syntax-variable: #d1383d; + --theme-syntax-string: #3d9a57; + --theme-syntax-number: #d68c27; + --theme-syntax-type: #b0851f; + --theme-syntax-operator: #318795; + --theme-syntax-punctuation: #1a1a1a; +} + +[data-theme="aura"][data-dark="false"] { + --theme-primary: #a277ff; + --theme-secondary: #f694ff; + --theme-accent: #a277ff; + --theme-error: #ff6767; + --theme-warning: #ffca85; + --theme-success: #61ffca; + --theme-info: #a277ff; + --theme-text: #edecee; + --theme-text-muted: #6d6d6d; + --theme-background: #0f0f0f; + --theme-background-panel: #15141b; + --theme-background-element: #15141b; + --theme-border: #2d2d2d; + --theme-border-active: #6d6d6d; + --theme-border-subtle: #2d2d2d; + --theme-diff-added: #61ffca; + --theme-diff-removed: #ff6767; + --theme-diff-context: #6d6d6d; + --theme-diff-hunk-header: #6d6d6d; + --theme-diff-highlight-added: #61ffca; + --theme-diff-highlight-removed: #ff6767; + --theme-diff-added-bg: #354933; + --theme-diff-removed-bg: #3f191a; + --theme-diff-context-bg: #15141b; + --theme-diff-line-number: #2d2d2d; + --theme-diff-added-line-number-bg: #162620; + --theme-diff-removed-line-number-bg: #26161a; + --theme-markdown-text: #edecee; + --theme-markdown-heading: #a277ff; + --theme-markdown-link: #f694ff; + --theme-markdown-link-text: #a277ff; + --theme-markdown-code: #61ffca; + --theme-markdown-block-quote: #6d6d6d; + --theme-markdown-emph: #ffca85; + --theme-markdown-strong: #a277ff; + --theme-markdown-horizontal-rule: #6d6d6d; + --theme-markdown-list-item: #a277ff; + --theme-markdown-list-enumeration: #a277ff; + --theme-markdown-image: #f694ff; + --theme-markdown-image-text: #a277ff; + --theme-markdown-code-block: #edecee; + --theme-syntax-comment: #6d6d6d; + --theme-syntax-keyword: #f694ff; + --theme-syntax-function: #a277ff; + --theme-syntax-variable: #a277ff; + --theme-syntax-string: #61ffca; + --theme-syntax-number: #9dff65; + --theme-syntax-type: #a277ff; + --theme-syntax-operator: #f694ff; + --theme-syntax-punctuation: #edecee; +} + +[data-theme="aura"][data-dark="true"] { + --theme-primary: #a277ff; + --theme-secondary: #f694ff; + --theme-accent: #a277ff; + --theme-error: #ff6767; + --theme-warning: #ffca85; + --theme-success: #61ffca; + --theme-info: #a277ff; + --theme-text: #edecee; + --theme-text-muted: #6d6d6d; + --theme-background: #0f0f0f; + --theme-background-panel: #15141b; + --theme-background-element: #15141b; + --theme-border: #2d2d2d; + --theme-border-active: #6d6d6d; + --theme-border-subtle: #2d2d2d; + --theme-diff-added: #61ffca; + --theme-diff-removed: #ff6767; + --theme-diff-context: #6d6d6d; + --theme-diff-hunk-header: #6d6d6d; + --theme-diff-highlight-added: #61ffca; + --theme-diff-highlight-removed: #ff6767; + --theme-diff-added-bg: #354933; + --theme-diff-removed-bg: #3f191a; + --theme-diff-context-bg: #15141b; + --theme-diff-line-number: #2d2d2d; + --theme-diff-added-line-number-bg: #162620; + --theme-diff-removed-line-number-bg: #26161a; + --theme-markdown-text: #edecee; + --theme-markdown-heading: #a277ff; + --theme-markdown-link: #f694ff; + --theme-markdown-link-text: #a277ff; + --theme-markdown-code: #61ffca; + --theme-markdown-block-quote: #6d6d6d; + --theme-markdown-emph: #ffca85; + --theme-markdown-strong: #a277ff; + --theme-markdown-horizontal-rule: #6d6d6d; + --theme-markdown-list-item: #a277ff; + --theme-markdown-list-enumeration: #a277ff; + --theme-markdown-image: #f694ff; + --theme-markdown-image-text: #a277ff; + --theme-markdown-code-block: #edecee; + --theme-syntax-comment: #6d6d6d; + --theme-syntax-keyword: #f694ff; + --theme-syntax-function: #a277ff; + --theme-syntax-variable: #a277ff; + --theme-syntax-string: #61ffca; + --theme-syntax-number: #9dff65; + --theme-syntax-type: #a277ff; + --theme-syntax-operator: #f694ff; + --theme-syntax-punctuation: #edecee; +} + +[data-theme="ayu"][data-dark="false"] { + --theme-primary: #59c2ff; + --theme-secondary: #d2a6ff; + --theme-accent: #e6b450; + --theme-error: #d95757; + --theme-warning: #e6b673; + --theme-success: #7fd962; + --theme-info: #39bae6; + --theme-text: #bfbdb6; + --theme-text-muted: #565b66; + --theme-background: #0b0e14; + --theme-background-panel: #0f131a; + --theme-background-element: #0d1017; + --theme-border: #6c7380; + --theme-border-active: #6c7380; + --theme-border-subtle: #11151c; + --theme-diff-added: #7fd962; + --theme-diff-removed: #f26d78; + --theme-diff-context: #acb6bf; + --theme-diff-hunk-header: #acb6bf; + --theme-diff-highlight-added: #aad94c; + --theme-diff-highlight-removed: #f07178; + --theme-diff-added-bg: #20303b; + --theme-diff-removed-bg: #37222c; + --theme-diff-context-bg: #0f131a; + --theme-diff-line-number: #6c7380; + --theme-diff-added-line-number-bg: #1b2b34; + --theme-diff-removed-line-number-bg: #2d1f26; + --theme-markdown-text: #bfbdb6; + --theme-markdown-heading: #d2a6ff; + --theme-markdown-link: #59c2ff; + --theme-markdown-link-text: #39bae6; + --theme-markdown-code: #aad94c; + --theme-markdown-block-quote: #e6b673; + --theme-markdown-emph: #e6b673; + --theme-markdown-strong: #ffb454; + --theme-markdown-horizontal-rule: #565b66; + --theme-markdown-list-item: #59c2ff; + --theme-markdown-list-enumeration: #39bae6; + --theme-markdown-image: #59c2ff; + --theme-markdown-image-text: #39bae6; + --theme-markdown-code-block: #bfbdb6; + --theme-syntax-comment: #acb6bf; + --theme-syntax-keyword: #ff8f40; + --theme-syntax-function: #ffb454; + --theme-syntax-variable: #59c2ff; + --theme-syntax-string: #aad94c; + --theme-syntax-number: #d2a6ff; + --theme-syntax-type: #e6b673; + --theme-syntax-operator: #f29668; + --theme-syntax-punctuation: #bfbdb6; +} + +[data-theme="ayu"][data-dark="true"] { + --theme-primary: #59c2ff; + --theme-secondary: #d2a6ff; + --theme-accent: #e6b450; + --theme-error: #d95757; + --theme-warning: #e6b673; + --theme-success: #7fd962; + --theme-info: #39bae6; + --theme-text: #bfbdb6; + --theme-text-muted: #565b66; + --theme-background: #0b0e14; + --theme-background-panel: #0f131a; + --theme-background-element: #0d1017; + --theme-border: #6c7380; + --theme-border-active: #6c7380; + --theme-border-subtle: #11151c; + --theme-diff-added: #7fd962; + --theme-diff-removed: #f26d78; + --theme-diff-context: #acb6bf; + --theme-diff-hunk-header: #acb6bf; + --theme-diff-highlight-added: #aad94c; + --theme-diff-highlight-removed: #f07178; + --theme-diff-added-bg: #20303b; + --theme-diff-removed-bg: #37222c; + --theme-diff-context-bg: #0f131a; + --theme-diff-line-number: #6c7380; + --theme-diff-added-line-number-bg: #1b2b34; + --theme-diff-removed-line-number-bg: #2d1f26; + --theme-markdown-text: #bfbdb6; + --theme-markdown-heading: #d2a6ff; + --theme-markdown-link: #59c2ff; + --theme-markdown-link-text: #39bae6; + --theme-markdown-code: #aad94c; + --theme-markdown-block-quote: #e6b673; + --theme-markdown-emph: #e6b673; + --theme-markdown-strong: #ffb454; + --theme-markdown-horizontal-rule: #565b66; + --theme-markdown-list-item: #59c2ff; + --theme-markdown-list-enumeration: #39bae6; + --theme-markdown-image: #59c2ff; + --theme-markdown-image-text: #39bae6; + --theme-markdown-code-block: #bfbdb6; + --theme-syntax-comment: #acb6bf; + --theme-syntax-keyword: #ff8f40; + --theme-syntax-function: #ffb454; + --theme-syntax-variable: #59c2ff; + --theme-syntax-string: #aad94c; + --theme-syntax-number: #d2a6ff; + --theme-syntax-type: #e6b673; + --theme-syntax-operator: #f29668; + --theme-syntax-punctuation: #bfbdb6; +} + +[data-theme="catppuccin"][data-dark="false"] { + --theme-primary: #1e66f5; + --theme-secondary: #8839ef; + --theme-accent: #ea76cb; + --theme-error: #d20f39; + --theme-warning: #df8e1d; + --theme-success: #40a02b; + --theme-info: #179299; + --theme-text: #4c4f69; + --theme-text-muted: #5c5f77; + --theme-background: #eff1f5; + --theme-background-panel: #e6e9ef; + --theme-background-element: #dce0e8; + --theme-border: #ccd0da; + --theme-border-active: #bcc0cc; + --theme-border-subtle: #acb0be; + --theme-diff-added: #40a02b; + --theme-diff-removed: #d20f39; + --theme-diff-context: #7c7f93; + --theme-diff-hunk-header: #fe640b; + --theme-diff-highlight-added: #40a02b; + --theme-diff-highlight-removed: #d20f39; + --theme-diff-added-bg: #d6f0d9; + --theme-diff-removed-bg: #f6dfe2; + --theme-diff-context-bg: #e6e9ef; + --theme-diff-line-number: #bcc0cc; + --theme-diff-added-line-number-bg: #c9e3cb; + --theme-diff-removed-line-number-bg: #e9d3d6; + --theme-markdown-text: #4c4f69; + --theme-markdown-heading: #8839ef; + --theme-markdown-link: #1e66f5; + --theme-markdown-link-text: #04a5e5; + --theme-markdown-code: #40a02b; + --theme-markdown-block-quote: #df8e1d; + --theme-markdown-emph: #df8e1d; + --theme-markdown-strong: #fe640b; + --theme-markdown-horizontal-rule: #6c6f85; + --theme-markdown-list-item: #1e66f5; + --theme-markdown-list-enumeration: #04a5e5; + --theme-markdown-image: #1e66f5; + --theme-markdown-image-text: #04a5e5; + --theme-markdown-code-block: #4c4f69; + --theme-syntax-comment: #7c7f93; + --theme-syntax-keyword: #8839ef; + --theme-syntax-function: #1e66f5; + --theme-syntax-variable: #d20f39; + --theme-syntax-string: #40a02b; + --theme-syntax-number: #fe640b; + --theme-syntax-type: #df8e1d; + --theme-syntax-operator: #04a5e5; + --theme-syntax-punctuation: #4c4f69; +} + +[data-theme="catppuccin"][data-dark="true"] { + --theme-primary: #89b4fa; + --theme-secondary: #cba6f7; + --theme-accent: #f5c2e7; + --theme-error: #f38ba8; + --theme-warning: #f9e2af; + --theme-success: #a6e3a1; + --theme-info: #94e2d5; + --theme-text: #cdd6f4; + --theme-text-muted: #bac2de; + --theme-background: #1e1e2e; + --theme-background-panel: #181825; + --theme-background-element: #11111b; + --theme-border: #313244; + --theme-border-active: #45475a; + --theme-border-subtle: #585b70; + --theme-diff-added: #a6e3a1; + --theme-diff-removed: #f38ba8; + --theme-diff-context: #9399b2; + --theme-diff-hunk-header: #fab387; + --theme-diff-highlight-added: #a6e3a1; + --theme-diff-highlight-removed: #f38ba8; + --theme-diff-added-bg: #24312b; + --theme-diff-removed-bg: #3c2a32; + --theme-diff-context-bg: #181825; + --theme-diff-line-number: #45475a; + --theme-diff-added-line-number-bg: #1e2a25; + --theme-diff-removed-line-number-bg: #32232a; + --theme-markdown-text: #cdd6f4; + --theme-markdown-heading: #cba6f7; + --theme-markdown-link: #89b4fa; + --theme-markdown-link-text: #89dceb; + --theme-markdown-code: #a6e3a1; + --theme-markdown-block-quote: #f9e2af; + --theme-markdown-emph: #f9e2af; + --theme-markdown-strong: #fab387; + --theme-markdown-horizontal-rule: #a6adc8; + --theme-markdown-list-item: #89b4fa; + --theme-markdown-list-enumeration: #89dceb; + --theme-markdown-image: #89b4fa; + --theme-markdown-image-text: #89dceb; + --theme-markdown-code-block: #cdd6f4; + --theme-syntax-comment: #9399b2; + --theme-syntax-keyword: #cba6f7; + --theme-syntax-function: #89b4fa; + --theme-syntax-variable: #f38ba8; + --theme-syntax-string: #a6e3a1; + --theme-syntax-number: #fab387; + --theme-syntax-type: #f9e2af; + --theme-syntax-operator: #89dceb; + --theme-syntax-punctuation: #cdd6f4; +} + +[data-theme="cobalt2"][data-dark="false"] { + --theme-primary: #0066cc; + --theme-secondary: #7c4dff; + --theme-accent: #00acc1; + --theme-error: #e91e63; + --theme-warning: #ff9800; + --theme-success: #4caf50; + --theme-info: #ff5722; + --theme-text: #193549; + --theme-text-muted: #5c6b7d; + --theme-background: #ffffff; + --theme-background-panel: #f5f7fa; + --theme-background-element: #e8ecf1; + --theme-border: #d3dae3; + --theme-border-active: #0066cc; + --theme-border-subtle: #e8ecf1; + --theme-diff-added: #4caf50; + --theme-diff-removed: #e91e63; + --theme-diff-context: #5c6b7d; + --theme-diff-hunk-header: #00acc1; + --theme-diff-highlight-added: #4caf50; + --theme-diff-highlight-removed: #e91e63; + --theme-diff-added-bg: #e8f5e9; + --theme-diff-removed-bg: #ffebee; + --theme-diff-context-bg: #f5f7fa; + --theme-diff-line-number: #b0bec5; + --theme-diff-added-line-number-bg: #e8f5e9; + --theme-diff-removed-line-number-bg: #ffebee; + --theme-markdown-text: #193549; + --theme-markdown-heading: #ff9800; + --theme-markdown-link: #0066cc; + --theme-markdown-link-text: #00acc1; + --theme-markdown-code: #4caf50; + --theme-markdown-block-quote: #5c6b7d; + --theme-markdown-emph: #ff5722; + --theme-markdown-strong: #e91e63; + --theme-markdown-horizontal-rule: #d3dae3; + --theme-markdown-list-item: #0066cc; + --theme-markdown-list-enumeration: #00acc1; + --theme-markdown-image: #0066cc; + --theme-markdown-image-text: #00acc1; + --theme-markdown-code-block: #193549; + --theme-syntax-comment: #5c6b7d; + --theme-syntax-keyword: #ff5722; + --theme-syntax-function: #ff9800; + --theme-syntax-variable: #193549; + --theme-syntax-string: #4caf50; + --theme-syntax-number: #e91e63; + --theme-syntax-type: #00acc1; + --theme-syntax-operator: #ff5722; + --theme-syntax-punctuation: #193549; +} + +[data-theme="cobalt2"][data-dark="true"] { + --theme-primary: #0088ff; + --theme-secondary: #9a5feb; + --theme-accent: #2affdf; + --theme-error: #ff0088; + --theme-warning: #ffc600; + --theme-success: #9eff80; + --theme-info: #ff9d00; + --theme-text: #ffffff; + --theme-text-muted: #adb7c9; + --theme-background: #193549; + --theme-background-panel: #122738; + --theme-background-element: #1f4662; + --theme-border: #1f4662; + --theme-border-active: #0088ff; + --theme-border-subtle: #0e1e2e; + --theme-diff-added: #9eff80; + --theme-diff-removed: #ff0088; + --theme-diff-context: #adb7c9; + --theme-diff-hunk-header: #2affdf; + --theme-diff-highlight-added: #b9ff9f; + --theme-diff-highlight-removed: #ff5fb3; + --theme-diff-added-bg: #1a3a2a; + --theme-diff-removed-bg: #3a1a2a; + --theme-diff-context-bg: #122738; + --theme-diff-line-number: #2d5a7b; + --theme-diff-added-line-number-bg: #1a3a2a; + --theme-diff-removed-line-number-bg: #3a1a2a; + --theme-markdown-text: #ffffff; + --theme-markdown-heading: #ffc600; + --theme-markdown-link: #0088ff; + --theme-markdown-link-text: #2affdf; + --theme-markdown-code: #9eff80; + --theme-markdown-block-quote: #adb7c9; + --theme-markdown-emph: #ff9d00; + --theme-markdown-strong: #ff628c; + --theme-markdown-horizontal-rule: #2d5a7b; + --theme-markdown-list-item: #0088ff; + --theme-markdown-list-enumeration: #2affdf; + --theme-markdown-image: #0088ff; + --theme-markdown-image-text: #2affdf; + --theme-markdown-code-block: #ffffff; + --theme-syntax-comment: #0088ff; + --theme-syntax-keyword: #ff9d00; + --theme-syntax-function: #ffc600; + --theme-syntax-variable: #ffffff; + --theme-syntax-string: #9eff80; + --theme-syntax-number: #ff628c; + --theme-syntax-type: #2affdf; + --theme-syntax-operator: #ff9d00; + --theme-syntax-punctuation: #ffffff; +} + +[data-theme="dracula"][data-dark="false"] { + --theme-primary: #bd93f9; + --theme-secondary: #ff79c6; + --theme-accent: #8be9fd; + --theme-error: #ff5555; + --theme-warning: #f1fa8c; + --theme-success: #50fa7b; + --theme-info: #ffb86c; + --theme-text: #282a36; + --theme-text-muted: #6272a4; + --theme-background: #f8f8f2; + --theme-background-panel: #e8e8e2; + --theme-background-element: #d8d8d2; + --theme-border: #c8c8c2; + --theme-border-active: #bd93f9; + --theme-border-subtle: #e0e0e0; + --theme-diff-added: #50fa7b; + --theme-diff-removed: #ff5555; + --theme-diff-context: #6272a4; + --theme-diff-hunk-header: #6272a4; + --theme-diff-highlight-added: #50fa7b; + --theme-diff-highlight-removed: #ff5555; + --theme-diff-added-bg: #e0ffe0; + --theme-diff-removed-bg: #ffe0e0; + --theme-diff-context-bg: #e8e8e2; + --theme-diff-line-number: #c8c8c2; + --theme-diff-added-line-number-bg: #e0ffe0; + --theme-diff-removed-line-number-bg: #ffe0e0; + --theme-markdown-text: #282a36; + --theme-markdown-heading: #bd93f9; + --theme-markdown-link: #8be9fd; + --theme-markdown-link-text: #ff79c6; + --theme-markdown-code: #50fa7b; + --theme-markdown-block-quote: #6272a4; + --theme-markdown-emph: #f1fa8c; + --theme-markdown-strong: #ffb86c; + --theme-markdown-horizontal-rule: #6272a4; + --theme-markdown-list-item: #bd93f9; + --theme-markdown-list-enumeration: #8be9fd; + --theme-markdown-image: #8be9fd; + --theme-markdown-image-text: #ff79c6; + --theme-markdown-code-block: #282a36; + --theme-syntax-comment: #6272a4; + --theme-syntax-keyword: #ff79c6; + --theme-syntax-function: #50fa7b; + --theme-syntax-variable: #282a36; + --theme-syntax-string: #f1fa8c; + --theme-syntax-number: #bd93f9; + --theme-syntax-type: #8be9fd; + --theme-syntax-operator: #ff79c6; + --theme-syntax-punctuation: #282a36; +} + +[data-theme="dracula"][data-dark="true"] { + --theme-primary: #bd93f9; + --theme-secondary: #ff79c6; + --theme-accent: #8be9fd; + --theme-error: #ff5555; + --theme-warning: #f1fa8c; + --theme-success: #50fa7b; + --theme-info: #ffb86c; + --theme-text: #f8f8f2; + --theme-text-muted: #6272a4; + --theme-background: #282a36; + --theme-background-panel: #21222c; + --theme-background-element: #44475a; + --theme-border: #44475a; + --theme-border-active: #bd93f9; + --theme-border-subtle: #191a21; + --theme-diff-added: #50fa7b; + --theme-diff-removed: #ff5555; + --theme-diff-context: #6272a4; + --theme-diff-hunk-header: #6272a4; + --theme-diff-highlight-added: #50fa7b; + --theme-diff-highlight-removed: #ff5555; + --theme-diff-added-bg: #1a3a1a; + --theme-diff-removed-bg: #3a1a1a; + --theme-diff-context-bg: #21222c; + --theme-diff-line-number: #44475a; + --theme-diff-added-line-number-bg: #1a3a1a; + --theme-diff-removed-line-number-bg: #3a1a1a; + --theme-markdown-text: #f8f8f2; + --theme-markdown-heading: #bd93f9; + --theme-markdown-link: #8be9fd; + --theme-markdown-link-text: #ff79c6; + --theme-markdown-code: #50fa7b; + --theme-markdown-block-quote: #6272a4; + --theme-markdown-emph: #f1fa8c; + --theme-markdown-strong: #ffb86c; + --theme-markdown-horizontal-rule: #6272a4; + --theme-markdown-list-item: #bd93f9; + --theme-markdown-list-enumeration: #8be9fd; + --theme-markdown-image: #8be9fd; + --theme-markdown-image-text: #ff79c6; + --theme-markdown-code-block: #f8f8f2; + --theme-syntax-comment: #6272a4; + --theme-syntax-keyword: #ff79c6; + --theme-syntax-function: #50fa7b; + --theme-syntax-variable: #f8f8f2; + --theme-syntax-string: #f1fa8c; + --theme-syntax-number: #bd93f9; + --theme-syntax-type: #8be9fd; + --theme-syntax-operator: #ff79c6; + --theme-syntax-punctuation: #f8f8f2; +} + +[data-theme="everforest"][data-dark="false"] { + --theme-primary: #8da101; + --theme-secondary: #3a94c5; + --theme-accent: #df69ba; + --theme-error: #f85552; + --theme-warning: #f57d26; + --theme-success: #8da101; + --theme-info: #35a77c; + --theme-text: #5c6a72; + --theme-text-muted: #a6b0a0; + --theme-background: #fdf6e3; + --theme-background-panel: #efebd4; + --theme-background-element: #f4f0d9; + --theme-border: #939f91; + --theme-border-active: #829181; + --theme-border-subtle: #a6b0a0; + --theme-diff-added: #1e725c; + --theme-diff-removed: #c53b53; + --theme-diff-context: #7086b5; + --theme-diff-hunk-header: #7086b5; + --theme-diff-highlight-added: #4db380; + --theme-diff-highlight-removed: #f52a65; + --theme-diff-added-bg: #d5e5d5; + --theme-diff-removed-bg: #f7d8db; + --theme-diff-context-bg: #efebd4; + --theme-diff-line-number: #f4f0d9; + --theme-diff-added-line-number-bg: #c5d5c5; + --theme-diff-removed-line-number-bg: #e7c8cb; + --theme-markdown-text: #5c6a72; + --theme-markdown-heading: #df69ba; + --theme-markdown-link: #8da101; + --theme-markdown-link-text: #35a77c; + --theme-markdown-code: #8da101; + --theme-markdown-block-quote: #dfa000; + --theme-markdown-emph: #dfa000; + --theme-markdown-strong: #f57d26; + --theme-markdown-horizontal-rule: #a6b0a0; + --theme-markdown-list-item: #8da101; + --theme-markdown-list-enumeration: #35a77c; + --theme-markdown-image: #8da101; + --theme-markdown-image-text: #35a77c; + --theme-markdown-code-block: #5c6a72; + --theme-syntax-comment: #a6b0a0; + --theme-syntax-keyword: #df69ba; + --theme-syntax-function: #8da101; + --theme-syntax-variable: #f85552; + --theme-syntax-string: #8da101; + --theme-syntax-number: #f57d26; + --theme-syntax-type: #dfa000; + --theme-syntax-operator: #35a77c; + --theme-syntax-punctuation: #5c6a72; +} + +[data-theme="everforest"][data-dark="true"] { + --theme-primary: #a7c080; + --theme-secondary: #7fbbb3; + --theme-accent: #d699b6; + --theme-error: #e67e80; + --theme-warning: #e69875; + --theme-success: #a7c080; + --theme-info: #83c092; + --theme-text: #d3c6aa; + --theme-text-muted: #7a8478; + --theme-background: #2d353b; + --theme-background-panel: #333c43; + --theme-background-element: #343f44; + --theme-border: #859289; + --theme-border-active: #9da9a0; + --theme-border-subtle: #7a8478; + --theme-diff-added: #4fd6be; + --theme-diff-removed: #c53b53; + --theme-diff-context: #828bb8; + --theme-diff-hunk-header: #828bb8; + --theme-diff-highlight-added: #b8db87; + --theme-diff-highlight-removed: #e26a75; + --theme-diff-added-bg: #20303b; + --theme-diff-removed-bg: #37222c; + --theme-diff-context-bg: #333c43; + --theme-diff-line-number: #343f44; + --theme-diff-added-line-number-bg: #1b2b34; + --theme-diff-removed-line-number-bg: #2d1f26; + --theme-markdown-text: #d3c6aa; + --theme-markdown-heading: #d699b6; + --theme-markdown-link: #a7c080; + --theme-markdown-link-text: #83c092; + --theme-markdown-code: #a7c080; + --theme-markdown-block-quote: #dbbc7f; + --theme-markdown-emph: #dbbc7f; + --theme-markdown-strong: #e69875; + --theme-markdown-horizontal-rule: #7a8478; + --theme-markdown-list-item: #a7c080; + --theme-markdown-list-enumeration: #83c092; + --theme-markdown-image: #a7c080; + --theme-markdown-image-text: #83c092; + --theme-markdown-code-block: #d3c6aa; + --theme-syntax-comment: #7a8478; + --theme-syntax-keyword: #d699b6; + --theme-syntax-function: #a7c080; + --theme-syntax-variable: #e67e80; + --theme-syntax-string: #a7c080; + --theme-syntax-number: #e69875; + --theme-syntax-type: #dbbc7f; + --theme-syntax-operator: #83c092; + --theme-syntax-punctuation: #d3c6aa; +} + +[data-theme="github"][data-dark="false"] { + --theme-primary: #0969da; + --theme-secondary: #8250df; + --theme-accent: #1b7c83; + --theme-error: #cf222e; + --theme-warning: #9a6700; + --theme-success: #1a7f37; + --theme-info: #bc4c00; + --theme-text: #24292f; + --theme-text-muted: #57606a; + --theme-background: #ffffff; + --theme-background-panel: #f6f8fa; + --theme-background-element: #f0f3f6; + --theme-border: #d0d7de; + --theme-border-active: #0969da; + --theme-border-subtle: #d8dee4; + --theme-diff-added: #1a7f37; + --theme-diff-removed: #cf222e; + --theme-diff-context: #57606a; + --theme-diff-hunk-header: #0969da; + --theme-diff-highlight-added: #1a7f37; + --theme-diff-highlight-removed: #cf222e; + --theme-diff-added-bg: #dafbe1; + --theme-diff-removed-bg: #ffebe9; + --theme-diff-context-bg: #f6f8fa; + --theme-diff-line-number: #afb8c1; + --theme-diff-added-line-number-bg: #dafbe1; + --theme-diff-removed-line-number-bg: #ffebe9; + --theme-markdown-text: #24292f; + --theme-markdown-heading: #0969da; + --theme-markdown-link: #0969da; + --theme-markdown-link-text: #1b7c83; + --theme-markdown-code: #bf3989; + --theme-markdown-block-quote: #57606a; + --theme-markdown-emph: #9a6700; + --theme-markdown-strong: #bc4c00; + --theme-markdown-horizontal-rule: #d0d7de; + --theme-markdown-list-item: #0969da; + --theme-markdown-list-enumeration: #1b7c83; + --theme-markdown-image: #0969da; + --theme-markdown-image-text: #1b7c83; + --theme-markdown-code-block: #24292f; + --theme-syntax-comment: #57606a; + --theme-syntax-keyword: #cf222e; + --theme-syntax-function: #8250df; + --theme-syntax-variable: #bc4c00; + --theme-syntax-string: #0969da; + --theme-syntax-number: #1b7c83; + --theme-syntax-type: #bc4c00; + --theme-syntax-operator: #cf222e; + --theme-syntax-punctuation: #24292f; +} + +[data-theme="github"][data-dark="true"] { + --theme-primary: #58a6ff; + --theme-secondary: #bc8cff; + --theme-accent: #39c5cf; + --theme-error: #f85149; + --theme-warning: #e3b341; + --theme-success: #3fb950; + --theme-info: #d29922; + --theme-text: #c9d1d9; + --theme-text-muted: #8b949e; + --theme-background: #0d1117; + --theme-background-panel: #010409; + --theme-background-element: #161b22; + --theme-border: #30363d; + --theme-border-active: #58a6ff; + --theme-border-subtle: #21262d; + --theme-diff-added: #3fb950; + --theme-diff-removed: #f85149; + --theme-diff-context: #8b949e; + --theme-diff-hunk-header: #58a6ff; + --theme-diff-highlight-added: #3fb950; + --theme-diff-highlight-removed: #f85149; + --theme-diff-added-bg: #033a16; + --theme-diff-removed-bg: #67060c; + --theme-diff-context-bg: #010409; + --theme-diff-line-number: #484f58; + --theme-diff-added-line-number-bg: #033a16; + --theme-diff-removed-line-number-bg: #67060c; + --theme-markdown-text: #c9d1d9; + --theme-markdown-heading: #58a6ff; + --theme-markdown-link: #58a6ff; + --theme-markdown-link-text: #39c5cf; + --theme-markdown-code: #ff7b72; + --theme-markdown-block-quote: #8b949e; + --theme-markdown-emph: #e3b341; + --theme-markdown-strong: #d29922; + --theme-markdown-horizontal-rule: #30363d; + --theme-markdown-list-item: #58a6ff; + --theme-markdown-list-enumeration: #39c5cf; + --theme-markdown-image: #58a6ff; + --theme-markdown-image-text: #39c5cf; + --theme-markdown-code-block: #c9d1d9; + --theme-syntax-comment: #8b949e; + --theme-syntax-keyword: #ff7b72; + --theme-syntax-function: #bc8cff; + --theme-syntax-variable: #d29922; + --theme-syntax-string: #39c5cf; + --theme-syntax-number: #58a6ff; + --theme-syntax-type: #d29922; + --theme-syntax-operator: #ff7b72; + --theme-syntax-punctuation: #c9d1d9; +} + +[data-theme="gruvbox"][data-dark="false"] { + --theme-primary: #076678; + --theme-secondary: #8f3f71; + --theme-accent: #427b58; + --theme-error: #9d0006; + --theme-warning: #af3a03; + --theme-success: #79740e; + --theme-info: #b57614; + --theme-text: #3c3836; + --theme-text-muted: #7c6f64; + --theme-background: #fbf1c7; + --theme-background-panel: #ebdbb2; + --theme-background-element: #d5c4a1; + --theme-border: #bdae93; + --theme-border-active: #3c3836; + --theme-border-subtle: #d5c4a1; + --theme-diff-added: #79740e; + --theme-diff-removed: #9d0006; + --theme-diff-context: #7c6f64; + --theme-diff-hunk-header: #427b58; + --theme-diff-highlight-added: #79740e; + --theme-diff-highlight-removed: #9d0006; + --theme-diff-added-bg: #e2e0b5; + --theme-diff-removed-bg: #e9d8d5; + --theme-diff-context-bg: #ebdbb2; + --theme-diff-line-number: #bdae93; + --theme-diff-added-line-number-bg: #d4d2a9; + --theme-diff-removed-line-number-bg: #d8cbc8; + --theme-markdown-text: #3c3836; + --theme-markdown-heading: #076678; + --theme-markdown-link: #427b58; + --theme-markdown-link-text: #79740e; + --theme-markdown-code: #b57614; + --theme-markdown-block-quote: #7c6f64; + --theme-markdown-emph: #8f3f71; + --theme-markdown-strong: #af3a03; + --theme-markdown-horizontal-rule: #7c6f64; + --theme-markdown-list-item: #076678; + --theme-markdown-list-enumeration: #427b58; + --theme-markdown-image: #427b58; + --theme-markdown-image-text: #79740e; + --theme-markdown-code-block: #3c3836; + --theme-syntax-comment: #7c6f64; + --theme-syntax-keyword: #9d0006; + --theme-syntax-function: #79740e; + --theme-syntax-variable: #076678; + --theme-syntax-string: #b57614; + --theme-syntax-number: #8f3f71; + --theme-syntax-type: #427b58; + --theme-syntax-operator: #af3a03; + --theme-syntax-punctuation: #3c3836; +} + +[data-theme="gruvbox"][data-dark="true"] { + --theme-primary: #83a598; + --theme-secondary: #d3869b; + --theme-accent: #8ec07c; + --theme-error: #fb4934; + --theme-warning: #fe8019; + --theme-success: #b8bb26; + --theme-info: #fabd2f; + --theme-text: #ebdbb2; + --theme-text-muted: #928374; + --theme-background: #282828; + --theme-background-panel: #3c3836; + --theme-background-element: #504945; + --theme-border: #665c54; + --theme-border-active: #ebdbb2; + --theme-border-subtle: #504945; + --theme-diff-added: #98971a; + --theme-diff-removed: #cc241d; + --theme-diff-context: #928374; + --theme-diff-hunk-header: #689d6a; + --theme-diff-highlight-added: #b8bb26; + --theme-diff-highlight-removed: #fb4934; + --theme-diff-added-bg: #32302f; + --theme-diff-removed-bg: #322929; + --theme-diff-context-bg: #3c3836; + --theme-diff-line-number: #665c54; + --theme-diff-added-line-number-bg: #2a2827; + --theme-diff-removed-line-number-bg: #2a2222; + --theme-markdown-text: #ebdbb2; + --theme-markdown-heading: #83a598; + --theme-markdown-link: #8ec07c; + --theme-markdown-link-text: #b8bb26; + --theme-markdown-code: #fabd2f; + --theme-markdown-block-quote: #928374; + --theme-markdown-emph: #d3869b; + --theme-markdown-strong: #fe8019; + --theme-markdown-horizontal-rule: #928374; + --theme-markdown-list-item: #83a598; + --theme-markdown-list-enumeration: #8ec07c; + --theme-markdown-image: #8ec07c; + --theme-markdown-image-text: #b8bb26; + --theme-markdown-code-block: #ebdbb2; + --theme-syntax-comment: #928374; + --theme-syntax-keyword: #fb4934; + --theme-syntax-function: #b8bb26; + --theme-syntax-variable: #83a598; + --theme-syntax-string: #fabd2f; + --theme-syntax-number: #d3869b; + --theme-syntax-type: #8ec07c; + --theme-syntax-operator: #fe8019; + --theme-syntax-punctuation: #ebdbb2; +} + +[data-theme="kanagawa"][data-dark="false"] { + --theme-primary: #2d4f67; + --theme-secondary: #957fb8; + --theme-accent: #d27e99; + --theme-error: #e82424; + --theme-warning: #d7a657; + --theme-success: #98bb6c; + --theme-info: #76946a; + --theme-text: #54433a; + --theme-text-muted: #9e9389; + --theme-background: #f2e9de; + --theme-background-panel: #eae4d7; + --theme-background-element: #e3dcd2; + --theme-border: #d4cbbf; + --theme-border-active: #c38d9d; + --theme-border-subtle: #dcd4c9; + --theme-diff-added: #98bb6c; + --theme-diff-removed: #e82424; + --theme-diff-context: #9e9389; + --theme-diff-hunk-header: #2d4f67; + --theme-diff-highlight-added: #89af5b; + --theme-diff-highlight-removed: #d61f1f; + --theme-diff-added-bg: #eaf3e4; + --theme-diff-removed-bg: #fbe6e6; + --theme-diff-context-bg: #eae4d7; + --theme-diff-line-number: #c7beb4; + --theme-diff-added-line-number-bg: #dde8d6; + --theme-diff-removed-line-number-bg: #f2dada; + --theme-markdown-text: #54433a; + --theme-markdown-heading: #957fb8; + --theme-markdown-link: #2d4f67; + --theme-markdown-link-text: #76946a; + --theme-markdown-code: #98bb6c; + --theme-markdown-block-quote: #9e9389; + --theme-markdown-emph: #c38d9d; + --theme-markdown-strong: #d7a657; + --theme-markdown-horizontal-rule: #9e9389; + --theme-markdown-list-item: #2d4f67; + --theme-markdown-list-enumeration: #76946a; + --theme-markdown-image: #2d4f67; + --theme-markdown-image-text: #76946a; + --theme-markdown-code-block: #54433a; + --theme-syntax-comment: #9e9389; + --theme-syntax-keyword: #957fb8; + --theme-syntax-function: #2d4f67; + --theme-syntax-variable: #54433a; + --theme-syntax-string: #98bb6c; + --theme-syntax-number: #d7a657; + --theme-syntax-type: #c38d9d; + --theme-syntax-operator: #d27e99; + --theme-syntax-punctuation: #54433a; +} + +[data-theme="kanagawa"][data-dark="true"] { + --theme-primary: #7e9cd8; + --theme-secondary: #957fb8; + --theme-accent: #d27e99; + --theme-error: #e82424; + --theme-warning: #d7a657; + --theme-success: #98bb6c; + --theme-info: #76946a; + --theme-text: #dcd7ba; + --theme-text-muted: #727169; + --theme-background: #1f1f28; + --theme-background-panel: #2a2a37; + --theme-background-element: #363646; + --theme-border: #54546d; + --theme-border-active: #c38d9d; + --theme-border-subtle: #363646; + --theme-diff-added: #98bb6c; + --theme-diff-removed: #e82424; + --theme-diff-context: #727169; + --theme-diff-hunk-header: #2d4f67; + --theme-diff-highlight-added: #a9d977; + --theme-diff-highlight-removed: #f24a4a; + --theme-diff-added-bg: #252e25; + --theme-diff-removed-bg: #362020; + --theme-diff-context-bg: #2a2a37; + --theme-diff-line-number: #54546d; + --theme-diff-added-line-number-bg: #202820; + --theme-diff-removed-line-number-bg: #2d1c1c; + --theme-markdown-text: #dcd7ba; + --theme-markdown-heading: #957fb8; + --theme-markdown-link: #7e9cd8; + --theme-markdown-link-text: #76946a; + --theme-markdown-code: #98bb6c; + --theme-markdown-block-quote: #727169; + --theme-markdown-emph: #c38d9d; + --theme-markdown-strong: #d7a657; + --theme-markdown-horizontal-rule: #727169; + --theme-markdown-list-item: #7e9cd8; + --theme-markdown-list-enumeration: #76946a; + --theme-markdown-image: #7e9cd8; + --theme-markdown-image-text: #76946a; + --theme-markdown-code-block: #dcd7ba; + --theme-syntax-comment: #727169; + --theme-syntax-keyword: #957fb8; + --theme-syntax-function: #7e9cd8; + --theme-syntax-variable: #dcd7ba; + --theme-syntax-string: #98bb6c; + --theme-syntax-number: #d7a657; + --theme-syntax-type: #c38d9d; + --theme-syntax-operator: #d27e99; + --theme-syntax-punctuation: #dcd7ba; +} + +[data-theme="material"][data-dark="false"] { + --theme-primary: #6182b8; + --theme-secondary: #7c4dff; + --theme-accent: #39adb5; + --theme-error: #e53935; + --theme-warning: #ffb300; + --theme-success: #91b859; + --theme-info: #f4511e; + --theme-text: #263238; + --theme-text-muted: #90a4ae; + --theme-background: #fafafa; + --theme-background-panel: #f5f5f5; + --theme-background-element: #e7e7e8; + --theme-border: #e0e0e0; + --theme-border-active: #6182b8; + --theme-border-subtle: #eeeeee; + --theme-diff-added: #91b859; + --theme-diff-removed: #e53935; + --theme-diff-context: #90a4ae; + --theme-diff-hunk-header: #39adb5; + --theme-diff-highlight-added: #91b859; + --theme-diff-highlight-removed: #e53935; + --theme-diff-added-bg: #e8f5e9; + --theme-diff-removed-bg: #ffebee; + --theme-diff-context-bg: #f5f5f5; + --theme-diff-line-number: #cfd8dc; + --theme-diff-added-line-number-bg: #e8f5e9; + --theme-diff-removed-line-number-bg: #ffebee; + --theme-markdown-text: #263238; + --theme-markdown-heading: #6182b8; + --theme-markdown-link: #39adb5; + --theme-markdown-link-text: #7c4dff; + --theme-markdown-code: #91b859; + --theme-markdown-block-quote: #90a4ae; + --theme-markdown-emph: #ffb300; + --theme-markdown-strong: #f4511e; + --theme-markdown-horizontal-rule: #e0e0e0; + --theme-markdown-list-item: #6182b8; + --theme-markdown-list-enumeration: #39adb5; + --theme-markdown-image: #39adb5; + --theme-markdown-image-text: #7c4dff; + --theme-markdown-code-block: #263238; + --theme-syntax-comment: #90a4ae; + --theme-syntax-keyword: #7c4dff; + --theme-syntax-function: #6182b8; + --theme-syntax-variable: #263238; + --theme-syntax-string: #91b859; + --theme-syntax-number: #f4511e; + --theme-syntax-type: #ffb300; + --theme-syntax-operator: #39adb5; + --theme-syntax-punctuation: #263238; +} + +[data-theme="material"][data-dark="true"] { + --theme-primary: #82aaff; + --theme-secondary: #c792ea; + --theme-accent: #89ddff; + --theme-error: #f07178; + --theme-warning: #ffcb6b; + --theme-success: #c3e88d; + --theme-info: #ffcb6b; + --theme-text: #eeffff; + --theme-text-muted: #546e7a; + --theme-background: #263238; + --theme-background-panel: #1e272c; + --theme-background-element: #37474f; + --theme-border: #37474f; + --theme-border-active: #82aaff; + --theme-border-subtle: #1e272c; + --theme-diff-added: #c3e88d; + --theme-diff-removed: #f07178; + --theme-diff-context: #546e7a; + --theme-diff-hunk-header: #89ddff; + --theme-diff-highlight-added: #c3e88d; + --theme-diff-highlight-removed: #f07178; + --theme-diff-added-bg: #2e3c2b; + --theme-diff-removed-bg: #3c2b2b; + --theme-diff-context-bg: #1e272c; + --theme-diff-line-number: #37474f; + --theme-diff-added-line-number-bg: #2e3c2b; + --theme-diff-removed-line-number-bg: #3c2b2b; + --theme-markdown-text: #eeffff; + --theme-markdown-heading: #82aaff; + --theme-markdown-link: #89ddff; + --theme-markdown-link-text: #c792ea; + --theme-markdown-code: #c3e88d; + --theme-markdown-block-quote: #546e7a; + --theme-markdown-emph: #ffcb6b; + --theme-markdown-strong: #ffcb6b; + --theme-markdown-horizontal-rule: #37474f; + --theme-markdown-list-item: #82aaff; + --theme-markdown-list-enumeration: #89ddff; + --theme-markdown-image: #89ddff; + --theme-markdown-image-text: #c792ea; + --theme-markdown-code-block: #eeffff; + --theme-syntax-comment: #546e7a; + --theme-syntax-keyword: #c792ea; + --theme-syntax-function: #82aaff; + --theme-syntax-variable: #eeffff; + --theme-syntax-string: #c3e88d; + --theme-syntax-number: #ffcb6b; + --theme-syntax-type: #ffcb6b; + --theme-syntax-operator: #89ddff; + --theme-syntax-punctuation: #eeffff; +} + +[data-theme="matrix"][data-dark="false"] { + --theme-primary: #1cc24b; + --theme-secondary: #24f6d9; + --theme-accent: #c770ff; + --theme-error: #ff4b4b; + --theme-warning: #e6ff57; + --theme-success: #1cc24b; + --theme-info: #30b3ff; + --theme-text: #203022; + --theme-text-muted: #748476; + --theme-background: #eef3ea; + --theme-background-panel: #e4ebe1; + --theme-background-element: #dae1d7; + --theme-border: #748476; + --theme-border-active: #1cc24b; + --theme-border-subtle: #dae1d7; + --theme-diff-added: #1cc24b; + --theme-diff-removed: #ff4b4b; + --theme-diff-context: #748476; + --theme-diff-hunk-header: #30b3ff; + --theme-diff-highlight-added: #5dac7e; + --theme-diff-highlight-removed: #d53a3a; + --theme-diff-added-bg: #e0efde; + --theme-diff-removed-bg: #f9e5e5; + --theme-diff-context-bg: #e4ebe1; + --theme-diff-line-number: #748476; + --theme-diff-added-line-number-bg: #d6e7d2; + --theme-diff-removed-line-number-bg: #f2d2d2; + --theme-markdown-text: #203022; + --theme-markdown-heading: #24f6d9; + --theme-markdown-link: #30b3ff; + --theme-markdown-link-text: #24f6d9; + --theme-markdown-code: #1cc24b; + --theme-markdown-block-quote: #748476; + --theme-markdown-emph: #ffa83d; + --theme-markdown-strong: #e6ff57; + --theme-markdown-horizontal-rule: #748476; + --theme-markdown-list-item: #30b3ff; + --theme-markdown-list-enumeration: #24f6d9; + --theme-markdown-image: #30b3ff; + --theme-markdown-image-text: #24f6d9; + --theme-markdown-code-block: #203022; + --theme-syntax-comment: #748476; + --theme-syntax-keyword: #c770ff; + --theme-syntax-function: #30b3ff; + --theme-syntax-variable: #203022; + --theme-syntax-string: #1cc24b; + --theme-syntax-number: #ffa83d; + --theme-syntax-type: #e6ff57; + --theme-syntax-operator: #24f6d9; + --theme-syntax-punctuation: #203022; +} + +[data-theme="matrix"][data-dark="true"] { + --theme-primary: #2eff6a; + --theme-secondary: #00efff; + --theme-accent: #c770ff; + --theme-error: #ff4b4b; + --theme-warning: #e6ff57; + --theme-success: #62ff94; + --theme-info: #30b3ff; + --theme-text: #62ff94; + --theme-text-muted: #8ca391; + --theme-background: #0a0e0a; + --theme-background-panel: #0e130d; + --theme-background-element: #141c12; + --theme-border: #1e2a1b; + --theme-border-active: #2eff6a; + --theme-border-subtle: #141c12; + --theme-diff-added: #1cc24b; + --theme-diff-removed: #ff4b4b; + --theme-diff-context: #8ca391; + --theme-diff-hunk-header: #30b3ff; + --theme-diff-highlight-added: #77ffaf; + --theme-diff-highlight-removed: #ff7171; + --theme-diff-added-bg: #132616; + --theme-diff-removed-bg: #261212; + --theme-diff-context-bg: #0e130d; + --theme-diff-line-number: #1e2a1b; + --theme-diff-added-line-number-bg: #0f1b11; + --theme-diff-removed-line-number-bg: #1b1414; + --theme-markdown-text: #62ff94; + --theme-markdown-heading: #00efff; + --theme-markdown-link: #30b3ff; + --theme-markdown-link-text: #24f6d9; + --theme-markdown-code: #1cc24b; + --theme-markdown-block-quote: #8ca391; + --theme-markdown-emph: #ffa83d; + --theme-markdown-strong: #e6ff57; + --theme-markdown-horizontal-rule: #8ca391; + --theme-markdown-list-item: #30b3ff; + --theme-markdown-list-enumeration: #24f6d9; + --theme-markdown-image: #30b3ff; + --theme-markdown-image-text: #24f6d9; + --theme-markdown-code-block: #62ff94; + --theme-syntax-comment: #8ca391; + --theme-syntax-keyword: #c770ff; + --theme-syntax-function: #30b3ff; + --theme-syntax-variable: #62ff94; + --theme-syntax-string: #1cc24b; + --theme-syntax-number: #ffa83d; + --theme-syntax-type: #e6ff57; + --theme-syntax-operator: #24f6d9; + --theme-syntax-punctuation: #62ff94; +} + +[data-theme="monokai"][data-dark="false"] { + --theme-primary: #66d9ef; + --theme-secondary: #ae81ff; + --theme-accent: #a6e22e; + --theme-error: #f92672; + --theme-warning: #fd971f; + --theme-success: #a6e22e; + --theme-info: #fd971f; + --theme-text: #272822; + --theme-text-muted: #75715e; + --theme-background: #fafafa; + --theme-background-panel: #f0f0f0; + --theme-background-element: #e0e0e0; + --theme-border: #d0d0d0; + --theme-border-active: #66d9ef; + --theme-border-subtle: #e8e8e8; + --theme-diff-added: #a6e22e; + --theme-diff-removed: #f92672; + --theme-diff-context: #75715e; + --theme-diff-hunk-header: #75715e; + --theme-diff-highlight-added: #a6e22e; + --theme-diff-highlight-removed: #f92672; + --theme-diff-added-bg: #e0ffe0; + --theme-diff-removed-bg: #ffe0e0; + --theme-diff-context-bg: #f0f0f0; + --theme-diff-line-number: #d0d0d0; + --theme-diff-added-line-number-bg: #e0ffe0; + --theme-diff-removed-line-number-bg: #ffe0e0; + --theme-markdown-text: #272822; + --theme-markdown-heading: #f92672; + --theme-markdown-link: #66d9ef; + --theme-markdown-link-text: #ae81ff; + --theme-markdown-code: #a6e22e; + --theme-markdown-block-quote: #75715e; + --theme-markdown-emph: #fd971f; + --theme-markdown-strong: #fd971f; + --theme-markdown-horizontal-rule: #75715e; + --theme-markdown-list-item: #66d9ef; + --theme-markdown-list-enumeration: #ae81ff; + --theme-markdown-image: #66d9ef; + --theme-markdown-image-text: #ae81ff; + --theme-markdown-code-block: #272822; + --theme-syntax-comment: #75715e; + --theme-syntax-keyword: #f92672; + --theme-syntax-function: #a6e22e; + --theme-syntax-variable: #272822; + --theme-syntax-string: #fd971f; + --theme-syntax-number: #ae81ff; + --theme-syntax-type: #66d9ef; + --theme-syntax-operator: #f92672; + --theme-syntax-punctuation: #272822; +} + +[data-theme="monokai"][data-dark="true"] { + --theme-primary: #66d9ef; + --theme-secondary: #ae81ff; + --theme-accent: #a6e22e; + --theme-error: #f92672; + --theme-warning: #e6db74; + --theme-success: #a6e22e; + --theme-info: #fd971f; + --theme-text: #f8f8f2; + --theme-text-muted: #75715e; + --theme-background: #272822; + --theme-background-panel: #1e1f1c; + --theme-background-element: #3e3d32; + --theme-border: #3e3d32; + --theme-border-active: #66d9ef; + --theme-border-subtle: #1e1f1c; + --theme-diff-added: #a6e22e; + --theme-diff-removed: #f92672; + --theme-diff-context: #75715e; + --theme-diff-hunk-header: #75715e; + --theme-diff-highlight-added: #a6e22e; + --theme-diff-highlight-removed: #f92672; + --theme-diff-added-bg: #1a3a1a; + --theme-diff-removed-bg: #3a1a1a; + --theme-diff-context-bg: #1e1f1c; + --theme-diff-line-number: #3e3d32; + --theme-diff-added-line-number-bg: #1a3a1a; + --theme-diff-removed-line-number-bg: #3a1a1a; + --theme-markdown-text: #f8f8f2; + --theme-markdown-heading: #f92672; + --theme-markdown-link: #66d9ef; + --theme-markdown-link-text: #ae81ff; + --theme-markdown-code: #a6e22e; + --theme-markdown-block-quote: #75715e; + --theme-markdown-emph: #e6db74; + --theme-markdown-strong: #fd971f; + --theme-markdown-horizontal-rule: #75715e; + --theme-markdown-list-item: #66d9ef; + --theme-markdown-list-enumeration: #ae81ff; + --theme-markdown-image: #66d9ef; + --theme-markdown-image-text: #ae81ff; + --theme-markdown-code-block: #f8f8f2; + --theme-syntax-comment: #75715e; + --theme-syntax-keyword: #f92672; + --theme-syntax-function: #a6e22e; + --theme-syntax-variable: #f8f8f2; + --theme-syntax-string: #e6db74; + --theme-syntax-number: #ae81ff; + --theme-syntax-type: #66d9ef; + --theme-syntax-operator: #f92672; + --theme-syntax-punctuation: #f8f8f2; +} + +[data-theme="nord"][data-dark="false"] { + --theme-primary: #5e81ac; + --theme-secondary: #81a1c1; + --theme-accent: #8fbcbb; + --theme-error: #bf616a; + --theme-warning: #d08770; + --theme-success: #a3be8c; + --theme-info: #5e81ac; + --theme-text: #2e3440; + --theme-text-muted: #3b4252; + --theme-background: #eceff4; + --theme-background-panel: #e5e9f0; + --theme-background-element: #d8dee9; + --theme-border: #4c566a; + --theme-border-active: #434c5e; + --theme-border-subtle: #4c566a; + --theme-diff-added: #a3be8c; + --theme-diff-removed: #bf616a; + --theme-diff-context: #4c566a; + --theme-diff-hunk-header: #4c566a; + --theme-diff-highlight-added: #a3be8c; + --theme-diff-highlight-removed: #bf616a; + --theme-diff-added-bg: #e5e9f0; + --theme-diff-removed-bg: #e5e9f0; + --theme-diff-context-bg: #e5e9f0; + --theme-diff-line-number: #d8dee9; + --theme-diff-added-line-number-bg: #e5e9f0; + --theme-diff-removed-line-number-bg: #e5e9f0; + --theme-markdown-text: #2e3440; + --theme-markdown-heading: #5e81ac; + --theme-markdown-link: #81a1c1; + --theme-markdown-link-text: #8fbcbb; + --theme-markdown-code: #a3be8c; + --theme-markdown-block-quote: #4c566a; + --theme-markdown-emph: #d08770; + --theme-markdown-strong: #ebcb8b; + --theme-markdown-horizontal-rule: #4c566a; + --theme-markdown-list-item: #5e81ac; + --theme-markdown-list-enumeration: #8fbcbb; + --theme-markdown-image: #81a1c1; + --theme-markdown-image-text: #8fbcbb; + --theme-markdown-code-block: #2e3440; + --theme-syntax-comment: #4c566a; + --theme-syntax-keyword: #81a1c1; + --theme-syntax-function: #88c0d0; + --theme-syntax-variable: #8fbcbb; + --theme-syntax-string: #a3be8c; + --theme-syntax-number: #b48ead; + --theme-syntax-type: #8fbcbb; + --theme-syntax-operator: #81a1c1; + --theme-syntax-punctuation: #2e3440; +} + +[data-theme="nord"][data-dark="true"] { + --theme-primary: #88c0d0; + --theme-secondary: #81a1c1; + --theme-accent: #8fbcbb; + --theme-error: #bf616a; + --theme-warning: #d08770; + --theme-success: #a3be8c; + --theme-info: #88c0d0; + --theme-text: #eceff4; + --theme-text-muted: #8b95a7; + --theme-background: #2e3440; + --theme-background-panel: #3b4252; + --theme-background-element: #434c5e; + --theme-border: #434c5e; + --theme-border-active: #4c566a; + --theme-border-subtle: #434c5e; + --theme-diff-added: #a3be8c; + --theme-diff-removed: #bf616a; + --theme-diff-context: #8b95a7; + --theme-diff-hunk-header: #8b95a7; + --theme-diff-highlight-added: #a3be8c; + --theme-diff-highlight-removed: #bf616a; + --theme-diff-added-bg: #3b4252; + --theme-diff-removed-bg: #3b4252; + --theme-diff-context-bg: #3b4252; + --theme-diff-line-number: #434c5e; + --theme-diff-added-line-number-bg: #3b4252; + --theme-diff-removed-line-number-bg: #3b4252; + --theme-markdown-text: #d8dee9; + --theme-markdown-heading: #88c0d0; + --theme-markdown-link: #81a1c1; + --theme-markdown-link-text: #8fbcbb; + --theme-markdown-code: #a3be8c; + --theme-markdown-block-quote: #8b95a7; + --theme-markdown-emph: #d08770; + --theme-markdown-strong: #ebcb8b; + --theme-markdown-horizontal-rule: #8b95a7; + --theme-markdown-list-item: #88c0d0; + --theme-markdown-list-enumeration: #8fbcbb; + --theme-markdown-image: #81a1c1; + --theme-markdown-image-text: #8fbcbb; + --theme-markdown-code-block: #d8dee9; + --theme-syntax-comment: #8b95a7; + --theme-syntax-keyword: #81a1c1; + --theme-syntax-function: #88c0d0; + --theme-syntax-variable: #8fbcbb; + --theme-syntax-string: #a3be8c; + --theme-syntax-number: #b48ead; + --theme-syntax-type: #8fbcbb; + --theme-syntax-operator: #81a1c1; + --theme-syntax-punctuation: #d8dee9; +} + +[data-theme="one-dark"][data-dark="false"] { + --theme-primary: #4078f2; + --theme-secondary: #a626a4; + --theme-accent: #0184bc; + --theme-error: #e45649; + --theme-warning: #c18401; + --theme-success: #50a14f; + --theme-info: #986801; + --theme-text: #383a42; + --theme-text-muted: #a0a1a7; + --theme-background: #fafafa; + --theme-background-panel: #f0f0f1; + --theme-background-element: #eaeaeb; + --theme-border: #d1d1d2; + --theme-border-active: #4078f2; + --theme-border-subtle: #e0e0e1; + --theme-diff-added: #50a14f; + --theme-diff-removed: #e45649; + --theme-diff-context: #a0a1a7; + --theme-diff-hunk-header: #0184bc; + --theme-diff-highlight-added: #489447; + --theme-diff-highlight-removed: #d65145; + --theme-diff-added-bg: #eafbe9; + --theme-diff-removed-bg: #fce9e8; + --theme-diff-context-bg: #f0f0f1; + --theme-diff-line-number: #c9c9ca; + --theme-diff-added-line-number-bg: #e1f3df; + --theme-diff-removed-line-number-bg: #f5e2e1; + --theme-markdown-text: #383a42; + --theme-markdown-heading: #a626a4; + --theme-markdown-link: #4078f2; + --theme-markdown-link-text: #0184bc; + --theme-markdown-code: #50a14f; + --theme-markdown-block-quote: #a0a1a7; + --theme-markdown-emph: #c18401; + --theme-markdown-strong: #986801; + --theme-markdown-horizontal-rule: #a0a1a7; + --theme-markdown-list-item: #4078f2; + --theme-markdown-list-enumeration: #0184bc; + --theme-markdown-image: #4078f2; + --theme-markdown-image-text: #0184bc; + --theme-markdown-code-block: #383a42; + --theme-syntax-comment: #a0a1a7; + --theme-syntax-keyword: #a626a4; + --theme-syntax-function: #4078f2; + --theme-syntax-variable: #e45649; + --theme-syntax-string: #50a14f; + --theme-syntax-number: #986801; + --theme-syntax-type: #c18401; + --theme-syntax-operator: #0184bc; + --theme-syntax-punctuation: #383a42; +} + +[data-theme="one-dark"][data-dark="true"] { + --theme-primary: #61afef; + --theme-secondary: #c678dd; + --theme-accent: #56b6c2; + --theme-error: #e06c75; + --theme-warning: #e5c07b; + --theme-success: #98c379; + --theme-info: #d19a66; + --theme-text: #abb2bf; + --theme-text-muted: #5c6370; + --theme-background: #282c34; + --theme-background-panel: #21252b; + --theme-background-element: #353b45; + --theme-border: #393f4a; + --theme-border-active: #61afef; + --theme-border-subtle: #2c313a; + --theme-diff-added: #98c379; + --theme-diff-removed: #e06c75; + --theme-diff-context: #5c6370; + --theme-diff-hunk-header: #56b6c2; + --theme-diff-highlight-added: #aad482; + --theme-diff-highlight-removed: #e8828b; + --theme-diff-added-bg: #2c382b; + --theme-diff-removed-bg: #3a2d2f; + --theme-diff-context-bg: #21252b; + --theme-diff-line-number: #495162; + --theme-diff-added-line-number-bg: #283427; + --theme-diff-removed-line-number-bg: #36292b; + --theme-markdown-text: #abb2bf; + --theme-markdown-heading: #c678dd; + --theme-markdown-link: #61afef; + --theme-markdown-link-text: #56b6c2; + --theme-markdown-code: #98c379; + --theme-markdown-block-quote: #5c6370; + --theme-markdown-emph: #e5c07b; + --theme-markdown-strong: #d19a66; + --theme-markdown-horizontal-rule: #5c6370; + --theme-markdown-list-item: #61afef; + --theme-markdown-list-enumeration: #56b6c2; + --theme-markdown-image: #61afef; + --theme-markdown-image-text: #56b6c2; + --theme-markdown-code-block: #abb2bf; + --theme-syntax-comment: #5c6370; + --theme-syntax-keyword: #c678dd; + --theme-syntax-function: #61afef; + --theme-syntax-variable: #e06c75; + --theme-syntax-string: #98c379; + --theme-syntax-number: #d19a66; + --theme-syntax-type: #e5c07b; + --theme-syntax-operator: #56b6c2; + --theme-syntax-punctuation: #abb2bf; +} + +[data-theme="opencode"][data-dark="false"] { + --theme-primary: #3b7dd8; + --theme-secondary: #7b5bb6; + --theme-accent: #d68c27; + --theme-error: #d1383d; + --theme-warning: #d68c27; + --theme-success: #3d9a57; + --theme-info: #318795; + --theme-text: #1a1a1a; + --theme-text-muted: #8a8a8a; + --theme-background: #ffffff; + --theme-background-panel: #fafafa; + --theme-background-element: #f5f5f5; + --theme-border: #b8b8b8; + --theme-border-active: #a0a0a0; + --theme-border-subtle: #d4d4d4; + --theme-diff-added: #1e725c; + --theme-diff-removed: #c53b53; + --theme-diff-context: #7086b5; + --theme-diff-hunk-header: #7086b5; + --theme-diff-highlight-added: #4db380; + --theme-diff-highlight-removed: #f52a65; + --theme-diff-added-bg: #d5e5d5; + --theme-diff-removed-bg: #f7d8db; + --theme-diff-context-bg: #fafafa; + --theme-diff-line-number: #f5f5f5; + --theme-diff-added-line-number-bg: #c5d5c5; + --theme-diff-removed-line-number-bg: #e7c8cb; + --theme-markdown-text: #1a1a1a; + --theme-markdown-heading: #d68c27; + --theme-markdown-link: #3b7dd8; + --theme-markdown-link-text: #318795; + --theme-markdown-code: #3d9a57; + --theme-markdown-block-quote: #b0851f; + --theme-markdown-emph: #b0851f; + --theme-markdown-strong: #d68c27; + --theme-markdown-horizontal-rule: #8a8a8a; + --theme-markdown-list-item: #3b7dd8; + --theme-markdown-list-enumeration: #318795; + --theme-markdown-image: #3b7dd8; + --theme-markdown-image-text: #318795; + --theme-markdown-code-block: #1a1a1a; + --theme-syntax-comment: #8a8a8a; + --theme-syntax-keyword: #d68c27; + --theme-syntax-function: #3b7dd8; + --theme-syntax-variable: #d1383d; + --theme-syntax-string: #3d9a57; + --theme-syntax-number: #d68c27; + --theme-syntax-type: #b0851f; + --theme-syntax-operator: #318795; + --theme-syntax-punctuation: #1a1a1a; +} + +[data-theme="opencode"][data-dark="true"] { + --theme-primary: #fab283; + --theme-secondary: #5c9cf5; + --theme-accent: #9d7cd8; + --theme-error: #e06c75; + --theme-warning: #f5a742; + --theme-success: #7fd88f; + --theme-info: #56b6c2; + --theme-text: #eeeeee; + --theme-text-muted: #808080; + --theme-background: #0a0a0a; + --theme-background-panel: #141414; + --theme-background-element: #1e1e1e; + --theme-border: #484848; + --theme-border-active: #606060; + --theme-border-subtle: #3c3c3c; + --theme-diff-added: #4fd6be; + --theme-diff-removed: #c53b53; + --theme-diff-context: #828bb8; + --theme-diff-hunk-header: #828bb8; + --theme-diff-highlight-added: #b8db87; + --theme-diff-highlight-removed: #e26a75; + --theme-diff-added-bg: #20303b; + --theme-diff-removed-bg: #37222c; + --theme-diff-context-bg: #141414; + --theme-diff-line-number: #1e1e1e; + --theme-diff-added-line-number-bg: #1b2b34; + --theme-diff-removed-line-number-bg: #2d1f26; + --theme-markdown-text: #eeeeee; + --theme-markdown-heading: #9d7cd8; + --theme-markdown-link: #fab283; + --theme-markdown-link-text: #56b6c2; + --theme-markdown-code: #7fd88f; + --theme-markdown-block-quote: #e5c07b; + --theme-markdown-emph: #e5c07b; + --theme-markdown-strong: #f5a742; + --theme-markdown-horizontal-rule: #808080; + --theme-markdown-list-item: #fab283; + --theme-markdown-list-enumeration: #56b6c2; + --theme-markdown-image: #fab283; + --theme-markdown-image-text: #56b6c2; + --theme-markdown-code-block: #eeeeee; + --theme-syntax-comment: #808080; + --theme-syntax-keyword: #9d7cd8; + --theme-syntax-function: #fab283; + --theme-syntax-variable: #e06c75; + --theme-syntax-string: #7fd88f; + --theme-syntax-number: #f5a742; + --theme-syntax-type: #e5c07b; + --theme-syntax-operator: #56b6c2; + --theme-syntax-punctuation: #eeeeee; +} + +[data-theme="palenight"][data-dark="false"] { + --theme-primary: #4976eb; + --theme-secondary: #a854f2; + --theme-accent: #00acc1; + --theme-error: #e53935; + --theme-warning: #ffb300; + --theme-success: #91b859; + --theme-info: #f4511e; + --theme-text: #292d3e; + --theme-text-muted: #8796b0; + --theme-background: #fafafa; + --theme-background-panel: #f5f5f5; + --theme-background-element: #e7e7e8; + --theme-border: #e0e0e0; + --theme-border-active: #4976eb; + --theme-border-subtle: #eeeeee; + --theme-diff-added: #91b859; + --theme-diff-removed: #e53935; + --theme-diff-context: #8796b0; + --theme-diff-hunk-header: #00acc1; + --theme-diff-highlight-added: #91b859; + --theme-diff-highlight-removed: #e53935; + --theme-diff-added-bg: #e8f5e9; + --theme-diff-removed-bg: #ffebee; + --theme-diff-context-bg: #f5f5f5; + --theme-diff-line-number: #cfd8dc; + --theme-diff-added-line-number-bg: #e8f5e9; + --theme-diff-removed-line-number-bg: #ffebee; + --theme-markdown-text: #292d3e; + --theme-markdown-heading: #a854f2; + --theme-markdown-link: #4976eb; + --theme-markdown-link-text: #00acc1; + --theme-markdown-code: #91b859; + --theme-markdown-block-quote: #8796b0; + --theme-markdown-emph: #ffb300; + --theme-markdown-strong: #f4511e; + --theme-markdown-horizontal-rule: #8796b0; + --theme-markdown-list-item: #4976eb; + --theme-markdown-list-enumeration: #00acc1; + --theme-markdown-image: #4976eb; + --theme-markdown-image-text: #00acc1; + --theme-markdown-code-block: #292d3e; + --theme-syntax-comment: #8796b0; + --theme-syntax-keyword: #a854f2; + --theme-syntax-function: #4976eb; + --theme-syntax-variable: #292d3e; + --theme-syntax-string: #91b859; + --theme-syntax-number: #f4511e; + --theme-syntax-type: #ffb300; + --theme-syntax-operator: #00acc1; + --theme-syntax-punctuation: #292d3e; +} + +[data-theme="palenight"][data-dark="true"] { + --theme-primary: #82aaff; + --theme-secondary: #c792ea; + --theme-accent: #89ddff; + --theme-error: #f07178; + --theme-warning: #ffcb6b; + --theme-success: #c3e88d; + --theme-info: #f78c6c; + --theme-text: #a6accd; + --theme-text-muted: #676e95; + --theme-background: #292d3e; + --theme-background-panel: #1e2132; + --theme-background-element: #32364a; + --theme-border: #32364a; + --theme-border-active: #82aaff; + --theme-border-subtle: #1e2132; + --theme-diff-added: #c3e88d; + --theme-diff-removed: #f07178; + --theme-diff-context: #676e95; + --theme-diff-hunk-header: #89ddff; + --theme-diff-highlight-added: #c3e88d; + --theme-diff-highlight-removed: #f07178; + --theme-diff-added-bg: #2e3c2b; + --theme-diff-removed-bg: #3c2b2b; + --theme-diff-context-bg: #1e2132; + --theme-diff-line-number: #444760; + --theme-diff-added-line-number-bg: #2e3c2b; + --theme-diff-removed-line-number-bg: #3c2b2b; + --theme-markdown-text: #a6accd; + --theme-markdown-heading: #c792ea; + --theme-markdown-link: #82aaff; + --theme-markdown-link-text: #89ddff; + --theme-markdown-code: #c3e88d; + --theme-markdown-block-quote: #676e95; + --theme-markdown-emph: #ffcb6b; + --theme-markdown-strong: #f78c6c; + --theme-markdown-horizontal-rule: #676e95; + --theme-markdown-list-item: #82aaff; + --theme-markdown-list-enumeration: #89ddff; + --theme-markdown-image: #82aaff; + --theme-markdown-image-text: #89ddff; + --theme-markdown-code-block: #a6accd; + --theme-syntax-comment: #676e95; + --theme-syntax-keyword: #c792ea; + --theme-syntax-function: #82aaff; + --theme-syntax-variable: #a6accd; + --theme-syntax-string: #c3e88d; + --theme-syntax-number: #f78c6c; + --theme-syntax-type: #ffcb6b; + --theme-syntax-operator: #89ddff; + --theme-syntax-punctuation: #a6accd; +} + +[data-theme="rosepine"][data-dark="false"] { + --theme-primary: #31748f; + --theme-secondary: #907aa9; + --theme-accent: #d7827e; + --theme-error: #b4637a; + --theme-warning: #ea9d34; + --theme-success: #286983; + --theme-info: #56949f; + --theme-text: #575279; + --theme-text-muted: #9893a5; + --theme-background: #faf4ed; + --theme-background-panel: #fffaf3; + --theme-background-element: #f2e9e1; + --theme-border: #dfdad9; + --theme-border-active: #31748f; + --theme-border-subtle: #f4ede8; + --theme-diff-added: #286983; + --theme-diff-removed: #b4637a; + --theme-diff-context: #9893a5; + --theme-diff-hunk-header: #907aa9; + --theme-diff-highlight-added: #286983; + --theme-diff-highlight-removed: #b4637a; + --theme-diff-added-bg: #e5f2f3; + --theme-diff-removed-bg: #fce5e8; + --theme-diff-context-bg: #fffaf3; + --theme-diff-line-number: #9893a5; + --theme-diff-added-line-number-bg: #e5f2f3; + --theme-diff-removed-line-number-bg: #fce5e8; + --theme-markdown-text: #575279; + --theme-markdown-heading: #907aa9; + --theme-markdown-link: #31748f; + --theme-markdown-link-text: #d7827e; + --theme-markdown-code: #286983; + --theme-markdown-block-quote: #9893a5; + --theme-markdown-emph: #ea9d34; + --theme-markdown-strong: #b4637a; + --theme-markdown-horizontal-rule: #dfdad9; + --theme-markdown-list-item: #31748f; + --theme-markdown-list-enumeration: #d7827e; + --theme-markdown-image: #31748f; + --theme-markdown-image-text: #d7827e; + --theme-markdown-code-block: #575279; + --theme-syntax-comment: #9893a5; + --theme-syntax-keyword: #286983; + --theme-syntax-function: #d7827e; + --theme-syntax-variable: #575279; + --theme-syntax-string: #ea9d34; + --theme-syntax-number: #907aa9; + --theme-syntax-type: #56949f; + --theme-syntax-operator: #797593; + --theme-syntax-punctuation: #797593; +} + +[data-theme="rosepine"][data-dark="true"] { + --theme-primary: #9ccfd8; + --theme-secondary: #c4a7e7; + --theme-accent: #ebbcba; + --theme-error: #eb6f92; + --theme-warning: #f6c177; + --theme-success: #31748f; + --theme-info: #9ccfd8; + --theme-text: #e0def4; + --theme-text-muted: #6e6a86; + --theme-background: #191724; + --theme-background-panel: #1f1d2e; + --theme-background-element: #26233a; + --theme-border: #403d52; + --theme-border-active: #9ccfd8; + --theme-border-subtle: #21202e; + --theme-diff-added: #31748f; + --theme-diff-removed: #eb6f92; + --theme-diff-context: #6e6a86; + --theme-diff-hunk-header: #c4a7e7; + --theme-diff-highlight-added: #31748f; + --theme-diff-highlight-removed: #eb6f92; + --theme-diff-added-bg: #1f2d3a; + --theme-diff-removed-bg: #3a1f2d; + --theme-diff-context-bg: #1f1d2e; + --theme-diff-line-number: #6e6a86; + --theme-diff-added-line-number-bg: #1f2d3a; + --theme-diff-removed-line-number-bg: #3a1f2d; + --theme-markdown-text: #e0def4; + --theme-markdown-heading: #c4a7e7; + --theme-markdown-link: #9ccfd8; + --theme-markdown-link-text: #ebbcba; + --theme-markdown-code: #31748f; + --theme-markdown-block-quote: #6e6a86; + --theme-markdown-emph: #f6c177; + --theme-markdown-strong: #eb6f92; + --theme-markdown-horizontal-rule: #403d52; + --theme-markdown-list-item: #9ccfd8; + --theme-markdown-list-enumeration: #ebbcba; + --theme-markdown-image: #9ccfd8; + --theme-markdown-image-text: #ebbcba; + --theme-markdown-code-block: #e0def4; + --theme-syntax-comment: #6e6a86; + --theme-syntax-keyword: #31748f; + --theme-syntax-function: #ebbcba; + --theme-syntax-variable: #e0def4; + --theme-syntax-string: #f6c177; + --theme-syntax-number: #c4a7e7; + --theme-syntax-type: #9ccfd8; + --theme-syntax-operator: #908caa; + --theme-syntax-punctuation: #908caa; +} + +[data-theme="solarized"][data-dark="false"] { + --theme-primary: #268bd2; + --theme-secondary: #6c71c4; + --theme-accent: #2aa198; + --theme-error: #dc322f; + --theme-warning: #b58900; + --theme-success: #859900; + --theme-info: #cb4b16; + --theme-text: #657b83; + --theme-text-muted: #93a1a1; + --theme-background: #fdf6e3; + --theme-background-panel: #eee8d5; + --theme-background-element: #eee8d5; + --theme-border: #eee8d5; + --theme-border-active: #93a1a1; + --theme-border-subtle: #eee8d5; + --theme-diff-added: #859900; + --theme-diff-removed: #dc322f; + --theme-diff-context: #93a1a1; + --theme-diff-hunk-header: #93a1a1; + --theme-diff-highlight-added: #859900; + --theme-diff-highlight-removed: #dc322f; + --theme-diff-added-bg: #eee8d5; + --theme-diff-removed-bg: #eee8d5; + --theme-diff-context-bg: #eee8d5; + --theme-diff-line-number: #93a1a1; + --theme-diff-added-line-number-bg: #eee8d5; + --theme-diff-removed-line-number-bg: #eee8d5; + --theme-markdown-text: #657b83; + --theme-markdown-heading: #268bd2; + --theme-markdown-link: #2aa198; + --theme-markdown-link-text: #6c71c4; + --theme-markdown-code: #859900; + --theme-markdown-block-quote: #93a1a1; + --theme-markdown-emph: #b58900; + --theme-markdown-strong: #cb4b16; + --theme-markdown-horizontal-rule: #93a1a1; + --theme-markdown-list-item: #268bd2; + --theme-markdown-list-enumeration: #2aa198; + --theme-markdown-image: #2aa198; + --theme-markdown-image-text: #6c71c4; + --theme-markdown-code-block: #657b83; + --theme-syntax-comment: #93a1a1; + --theme-syntax-keyword: #859900; + --theme-syntax-function: #268bd2; + --theme-syntax-variable: #2aa198; + --theme-syntax-string: #2aa198; + --theme-syntax-number: #d33682; + --theme-syntax-type: #b58900; + --theme-syntax-operator: #859900; + --theme-syntax-punctuation: #657b83; +} + +[data-theme="solarized"][data-dark="true"] { + --theme-primary: #268bd2; + --theme-secondary: #6c71c4; + --theme-accent: #2aa198; + --theme-error: #dc322f; + --theme-warning: #b58900; + --theme-success: #859900; + --theme-info: #cb4b16; + --theme-text: #839496; + --theme-text-muted: #586e75; + --theme-background: #002b36; + --theme-background-panel: #073642; + --theme-background-element: #073642; + --theme-border: #073642; + --theme-border-active: #586e75; + --theme-border-subtle: #073642; + --theme-diff-added: #859900; + --theme-diff-removed: #dc322f; + --theme-diff-context: #586e75; + --theme-diff-hunk-header: #586e75; + --theme-diff-highlight-added: #859900; + --theme-diff-highlight-removed: #dc322f; + --theme-diff-added-bg: #073642; + --theme-diff-removed-bg: #073642; + --theme-diff-context-bg: #073642; + --theme-diff-line-number: #586e75; + --theme-diff-added-line-number-bg: #073642; + --theme-diff-removed-line-number-bg: #073642; + --theme-markdown-text: #839496; + --theme-markdown-heading: #268bd2; + --theme-markdown-link: #2aa198; + --theme-markdown-link-text: #6c71c4; + --theme-markdown-code: #859900; + --theme-markdown-block-quote: #586e75; + --theme-markdown-emph: #b58900; + --theme-markdown-strong: #cb4b16; + --theme-markdown-horizontal-rule: #586e75; + --theme-markdown-list-item: #268bd2; + --theme-markdown-list-enumeration: #2aa198; + --theme-markdown-image: #2aa198; + --theme-markdown-image-text: #6c71c4; + --theme-markdown-code-block: #839496; + --theme-syntax-comment: #586e75; + --theme-syntax-keyword: #859900; + --theme-syntax-function: #268bd2; + --theme-syntax-variable: #2aa198; + --theme-syntax-string: #2aa198; + --theme-syntax-number: #d33682; + --theme-syntax-type: #b58900; + --theme-syntax-operator: #859900; + --theme-syntax-punctuation: #839496; +} + +[data-theme="synthwave84"][data-dark="false"] { + --theme-primary: #00bcd4; + --theme-secondary: #e91e63; + --theme-accent: #9c27b0; + --theme-error: #f44336; + --theme-warning: #ff9800; + --theme-success: #4caf50; + --theme-info: #ff5722; + --theme-text: #262335; + --theme-text-muted: #5c5c8a; + --theme-background: #fafafa; + --theme-background-panel: #f5f5f5; + --theme-background-element: #eeeeee; + --theme-border: #e0e0e0; + --theme-border-active: #00bcd4; + --theme-border-subtle: #f0f0f0; + --theme-diff-added: #4caf50; + --theme-diff-removed: #f44336; + --theme-diff-context: #5c5c8a; + --theme-diff-hunk-header: #9c27b0; + --theme-diff-highlight-added: #4caf50; + --theme-diff-highlight-removed: #f44336; + --theme-diff-added-bg: #e8f5e9; + --theme-diff-removed-bg: #ffebee; + --theme-diff-context-bg: #f5f5f5; + --theme-diff-line-number: #b0b0b0; + --theme-diff-added-line-number-bg: #e8f5e9; + --theme-diff-removed-line-number-bg: #ffebee; + --theme-markdown-text: #262335; + --theme-markdown-heading: #e91e63; + --theme-markdown-link: #00bcd4; + --theme-markdown-link-text: #9c27b0; + --theme-markdown-code: #4caf50; + --theme-markdown-block-quote: #5c5c8a; + --theme-markdown-emph: #ff9800; + --theme-markdown-strong: #ff5722; + --theme-markdown-horizontal-rule: #e0e0e0; + --theme-markdown-list-item: #00bcd4; + --theme-markdown-list-enumeration: #9c27b0; + --theme-markdown-image: #00bcd4; + --theme-markdown-image-text: #9c27b0; + --theme-markdown-code-block: #262335; + --theme-syntax-comment: #5c5c8a; + --theme-syntax-keyword: #e91e63; + --theme-syntax-function: #ff5722; + --theme-syntax-variable: #262335; + --theme-syntax-string: #ff9800; + --theme-syntax-number: #9c27b0; + --theme-syntax-type: #00bcd4; + --theme-syntax-operator: #e91e63; + --theme-syntax-punctuation: #262335; +} + +[data-theme="synthwave84"][data-dark="true"] { + --theme-primary: #36f9f6; + --theme-secondary: #ff7edb; + --theme-accent: #b084eb; + --theme-error: #fe4450; + --theme-warning: #fede5d; + --theme-success: #72f1b8; + --theme-info: #ff8b39; + --theme-text: #ffffff; + --theme-text-muted: #848bbd; + --theme-background: #262335; + --theme-background-panel: #1e1a29; + --theme-background-element: #2a2139; + --theme-border: #495495; + --theme-border-active: #36f9f6; + --theme-border-subtle: #241b2f; + --theme-diff-added: #72f1b8; + --theme-diff-removed: #fe4450; + --theme-diff-context: #848bbd; + --theme-diff-hunk-header: #b084eb; + --theme-diff-highlight-added: #97f1d8; + --theme-diff-highlight-removed: #ff5e5b; + --theme-diff-added-bg: #1a3a2a; + --theme-diff-removed-bg: #3a1a2a; + --theme-diff-context-bg: #1e1a29; + --theme-diff-line-number: #495495; + --theme-diff-added-line-number-bg: #1a3a2a; + --theme-diff-removed-line-number-bg: #3a1a2a; + --theme-markdown-text: #ffffff; + --theme-markdown-heading: #ff7edb; + --theme-markdown-link: #36f9f6; + --theme-markdown-link-text: #b084eb; + --theme-markdown-code: #72f1b8; + --theme-markdown-block-quote: #848bbd; + --theme-markdown-emph: #fede5d; + --theme-markdown-strong: #ff8b39; + --theme-markdown-horizontal-rule: #495495; + --theme-markdown-list-item: #36f9f6; + --theme-markdown-list-enumeration: #b084eb; + --theme-markdown-image: #36f9f6; + --theme-markdown-image-text: #b084eb; + --theme-markdown-code-block: #ffffff; + --theme-syntax-comment: #848bbd; + --theme-syntax-keyword: #ff7edb; + --theme-syntax-function: #ff8b39; + --theme-syntax-variable: #ffffff; + --theme-syntax-string: #fede5d; + --theme-syntax-number: #b084eb; + --theme-syntax-type: #36f9f6; + --theme-syntax-operator: #ff7edb; + --theme-syntax-punctuation: #ffffff; +} + +[data-theme="tokyonight"][data-dark="false"] { + --theme-primary: #2e7de9; + --theme-secondary: #9854f1; + --theme-accent: #b15c00; + --theme-error: #f52a65; + --theme-warning: #b15c00; + --theme-success: #587539; + --theme-info: #2e7de9; + --theme-text: #3760bf; + --theme-text-muted: #8990a3; + --theme-background: #e1e2e7; + --theme-background-panel: #d5d6db; + --theme-background-element: #c8c9ce; + --theme-border: #737a8c; + --theme-border-active: #5a607d; + --theme-border-subtle: #9699a8; + --theme-diff-added: #1e725c; + --theme-diff-removed: #c53b53; + --theme-diff-context: #7086b5; + --theme-diff-hunk-header: #7086b5; + --theme-diff-highlight-added: #4db380; + --theme-diff-highlight-removed: #f52a65; + --theme-diff-added-bg: #d5e5d5; + --theme-diff-removed-bg: #f7d8db; + --theme-diff-context-bg: #d5d6db; + --theme-diff-line-number: #c8c9ce; + --theme-diff-added-line-number-bg: #c5d5c5; + --theme-diff-removed-line-number-bg: #e7c8cb; + --theme-markdown-text: #3760bf; + --theme-markdown-heading: #9854f1; + --theme-markdown-link: #2e7de9; + --theme-markdown-link-text: #007197; + --theme-markdown-code: #587539; + --theme-markdown-block-quote: #8c6c3e; + --theme-markdown-emph: #8c6c3e; + --theme-markdown-strong: #b15c00; + --theme-markdown-horizontal-rule: #8990a3; + --theme-markdown-list-item: #2e7de9; + --theme-markdown-list-enumeration: #007197; + --theme-markdown-image: #2e7de9; + --theme-markdown-image-text: #007197; + --theme-markdown-code-block: #3760bf; + --theme-syntax-comment: #8990a3; + --theme-syntax-keyword: #9854f1; + --theme-syntax-function: #2e7de9; + --theme-syntax-variable: #f52a65; + --theme-syntax-string: #587539; + --theme-syntax-number: #b15c00; + --theme-syntax-type: #8c6c3e; + --theme-syntax-operator: #007197; + --theme-syntax-punctuation: #3760bf; +} + +[data-theme="tokyonight"][data-dark="true"] { + --theme-primary: #82aaff; + --theme-secondary: #c099ff; + --theme-accent: #ff966c; + --theme-error: #ff757f; + --theme-warning: #ff966c; + --theme-success: #c3e88d; + --theme-info: #82aaff; + --theme-text: #c8d3f5; + --theme-text-muted: #828bb8; + --theme-background: #1a1b26; + --theme-background-panel: #1e2030; + --theme-background-element: #222436; + --theme-border: #737aa2; + --theme-border-active: #9099b2; + --theme-border-subtle: #545c7e; + --theme-diff-added: #4fd6be; + --theme-diff-removed: #c53b53; + --theme-diff-context: #828bb8; + --theme-diff-hunk-header: #828bb8; + --theme-diff-highlight-added: #b8db87; + --theme-diff-highlight-removed: #e26a75; + --theme-diff-added-bg: #20303b; + --theme-diff-removed-bg: #37222c; + --theme-diff-context-bg: #1e2030; + --theme-diff-line-number: #222436; + --theme-diff-added-line-number-bg: #1b2b34; + --theme-diff-removed-line-number-bg: #2d1f26; + --theme-markdown-text: #c8d3f5; + --theme-markdown-heading: #c099ff; + --theme-markdown-link: #82aaff; + --theme-markdown-link-text: #86e1fc; + --theme-markdown-code: #c3e88d; + --theme-markdown-block-quote: #ffc777; + --theme-markdown-emph: #ffc777; + --theme-markdown-strong: #ff966c; + --theme-markdown-horizontal-rule: #828bb8; + --theme-markdown-list-item: #82aaff; + --theme-markdown-list-enumeration: #86e1fc; + --theme-markdown-image: #82aaff; + --theme-markdown-image-text: #86e1fc; + --theme-markdown-code-block: #c8d3f5; + --theme-syntax-comment: #828bb8; + --theme-syntax-keyword: #c099ff; + --theme-syntax-function: #82aaff; + --theme-syntax-variable: #ff757f; + --theme-syntax-string: #c3e88d; + --theme-syntax-number: #ff966c; + --theme-syntax-type: #ffc777; + --theme-syntax-operator: #86e1fc; + --theme-syntax-punctuation: #c8d3f5; +} + +[data-theme="vesper"][data-dark="false"] { + --theme-primary: #ffc799; + --theme-secondary: #99ffe4; + --theme-accent: #ffc799; + --theme-error: #ff8080; + --theme-warning: #ffc799; + --theme-success: #99ffe4; + --theme-info: #ffc799; + --theme-text: #101010; + --theme-text-muted: #a0a0a0; + --theme-background: #fff; + --theme-background-panel: #f0f0f0; + --theme-background-element: #e0e0e0; + --theme-border: #d0d0d0; + --theme-border-active: #ffc799; + --theme-border-subtle: #e8e8e8; + --theme-diff-added: #99ffe4; + --theme-diff-removed: #ff8080; + --theme-diff-context: #a0a0a0; + --theme-diff-hunk-header: #a0a0a0; + --theme-diff-highlight-added: #99ffe4; + --theme-diff-highlight-removed: #ff8080; + --theme-diff-added-bg: #e8f5e8; + --theme-diff-removed-bg: #f5e8e8; + --theme-diff-context-bg: #f8f8f8; + --theme-diff-line-number: #808080; + --theme-diff-added-line-number-bg: #e8f5e8; + --theme-diff-removed-line-number-bg: #f5e8e8; + --theme-markdown-text: #101010; + --theme-markdown-heading: #ffc799; + --theme-markdown-link: #ffc799; + --theme-markdown-link-text: #a0a0a0; + --theme-markdown-code: #a0a0a0; + --theme-markdown-block-quote: #101010; + --theme-markdown-emph: #101010; + --theme-markdown-strong: #101010; + --theme-markdown-horizontal-rule: #65737e; + --theme-markdown-list-item: #101010; + --theme-markdown-list-enumeration: #101010; + --theme-markdown-image: #ffc799; + --theme-markdown-image-text: #a0a0a0; + --theme-markdown-code-block: #101010; + --theme-syntax-comment: #8b8b8b94; + --theme-syntax-keyword: #a0a0a0; + --theme-syntax-function: #ffc799; + --theme-syntax-variable: #101010; + --theme-syntax-string: #99ffe4; + --theme-syntax-number: #ffc799; + --theme-syntax-type: #ffc799; + --theme-syntax-operator: #a0a0a0; + --theme-syntax-punctuation: #101010; +} + +[data-theme="vesper"][data-dark="true"] { + --theme-primary: #ffc799; + --theme-secondary: #99ffe4; + --theme-accent: #ffc799; + --theme-error: #ff8080; + --theme-warning: #ffc799; + --theme-success: #99ffe4; + --theme-info: #ffc799; + --theme-text: #fff; + --theme-text-muted: #a0a0a0; + --theme-background: #101010; + --theme-background-panel: #101010; + --theme-background-element: #101010; + --theme-border: #282828; + --theme-border-active: #ffc799; + --theme-border-subtle: #1c1c1c; + --theme-diff-added: #99ffe4; + --theme-diff-removed: #ff8080; + --theme-diff-context: #a0a0a0; + --theme-diff-hunk-header: #a0a0a0; + --theme-diff-highlight-added: #99ffe4; + --theme-diff-highlight-removed: #ff8080; + --theme-diff-added-bg: #0d2818; + --theme-diff-removed-bg: #281a1a; + --theme-diff-context-bg: #101010; + --theme-diff-line-number: #505050; + --theme-diff-added-line-number-bg: #0d2818; + --theme-diff-removed-line-number-bg: #281a1a; + --theme-markdown-text: #fff; + --theme-markdown-heading: #ffc799; + --theme-markdown-link: #ffc799; + --theme-markdown-link-text: #a0a0a0; + --theme-markdown-code: #a0a0a0; + --theme-markdown-block-quote: #fff; + --theme-markdown-emph: #fff; + --theme-markdown-strong: #fff; + --theme-markdown-horizontal-rule: #65737e; + --theme-markdown-list-item: #fff; + --theme-markdown-list-enumeration: #fff; + --theme-markdown-image: #ffc799; + --theme-markdown-image-text: #a0a0a0; + --theme-markdown-code-block: #fff; + --theme-syntax-comment: #8b8b8b94; + --theme-syntax-keyword: #a0a0a0; + --theme-syntax-function: #ffc799; + --theme-syntax-variable: #fff; + --theme-syntax-string: #99ffe4; + --theme-syntax-number: #ffc799; + --theme-syntax-type: #ffc799; + --theme-syntax-operator: #a0a0a0; + --theme-syntax-punctuation: #fff; +} + +[data-theme="zenburn"][data-dark="false"] { + --theme-primary: #5f7f8f; + --theme-secondary: #8f5f8f; + --theme-accent: #5f8f8f; + --theme-error: #8f5f5f; + --theme-warning: #8f8f5f; + --theme-success: #5f8f5f; + --theme-info: #8f7f5f; + --theme-text: #3f3f3f; + --theme-text-muted: #6f6f6f; + --theme-background: #ffffef; + --theme-background-panel: #f5f5e5; + --theme-background-element: #ebebdb; + --theme-border: #d0d0c0; + --theme-border-active: #5f7f8f; + --theme-border-subtle: #e0e0d0; + --theme-diff-added: #5f8f5f; + --theme-diff-removed: #8f5f5f; + --theme-diff-context: #6f6f6f; + --theme-diff-hunk-header: #5f8f8f; + --theme-diff-highlight-added: #5f8f5f; + --theme-diff-highlight-removed: #8f5f5f; + --theme-diff-added-bg: #efffef; + --theme-diff-removed-bg: #ffefef; + --theme-diff-context-bg: #f5f5e5; + --theme-diff-line-number: #b0b0a0; + --theme-diff-added-line-number-bg: #efffef; + --theme-diff-removed-line-number-bg: #ffefef; + --theme-markdown-text: #3f3f3f; + --theme-markdown-heading: #8f8f5f; + --theme-markdown-link: #5f7f8f; + --theme-markdown-link-text: #5f8f8f; + --theme-markdown-code: #5f8f5f; + --theme-markdown-block-quote: #6f6f6f; + --theme-markdown-emph: #8f8f5f; + --theme-markdown-strong: #8f7f5f; + --theme-markdown-horizontal-rule: #6f6f6f; + --theme-markdown-list-item: #5f7f8f; + --theme-markdown-list-enumeration: #5f8f8f; + --theme-markdown-image: #5f7f8f; + --theme-markdown-image-text: #5f8f8f; + --theme-markdown-code-block: #3f3f3f; + --theme-syntax-comment: #5f7f5f; + --theme-syntax-keyword: #8f8f5f; + --theme-syntax-function: #5f7f8f; + --theme-syntax-variable: #3f3f3f; + --theme-syntax-string: #8f5f5f; + --theme-syntax-number: #5f8f5f; + --theme-syntax-type: #5f8f8f; + --theme-syntax-operator: #8f8f5f; + --theme-syntax-punctuation: #3f3f3f; +} + +[data-theme="zenburn"][data-dark="true"] { + --theme-primary: #8cd0d3; + --theme-secondary: #dc8cc3; + --theme-accent: #93e0e3; + --theme-error: #cc9393; + --theme-warning: #f0dfaf; + --theme-success: #7f9f7f; + --theme-info: #dfaf8f; + --theme-text: #dcdccc; + --theme-text-muted: #9f9f9f; + --theme-background: #3f3f3f; + --theme-background-panel: #4f4f4f; + --theme-background-element: #5f5f5f; + --theme-border: #5f5f5f; + --theme-border-active: #8cd0d3; + --theme-border-subtle: #4f4f4f; + --theme-diff-added: #7f9f7f; + --theme-diff-removed: #cc9393; + --theme-diff-context: #9f9f9f; + --theme-diff-hunk-header: #93e0e3; + --theme-diff-highlight-added: #8fb28f; + --theme-diff-highlight-removed: #dca3a3; + --theme-diff-added-bg: #4f5f4f; + --theme-diff-removed-bg: #5f4f4f; + --theme-diff-context-bg: #4f4f4f; + --theme-diff-line-number: #6f6f6f; + --theme-diff-added-line-number-bg: #4f5f4f; + --theme-diff-removed-line-number-bg: #5f4f4f; + --theme-markdown-text: #dcdccc; + --theme-markdown-heading: #f0dfaf; + --theme-markdown-link: #8cd0d3; + --theme-markdown-link-text: #93e0e3; + --theme-markdown-code: #7f9f7f; + --theme-markdown-block-quote: #9f9f9f; + --theme-markdown-emph: #e0cf9f; + --theme-markdown-strong: #dfaf8f; + --theme-markdown-horizontal-rule: #9f9f9f; + --theme-markdown-list-item: #8cd0d3; + --theme-markdown-list-enumeration: #93e0e3; + --theme-markdown-image: #8cd0d3; + --theme-markdown-image-text: #93e0e3; + --theme-markdown-code-block: #dcdccc; + --theme-syntax-comment: #7f9f7f; + --theme-syntax-keyword: #f0dfaf; + --theme-syntax-function: #8cd0d3; + --theme-syntax-variable: #dcdccc; + --theme-syntax-string: #cc9393; + --theme-syntax-number: #8fb28f; + --theme-syntax-type: #93e0e3; + --theme-syntax-operator: #f0dfaf; + --theme-syntax-punctuation: #dcdccc; +} + diff --git a/packages/desktop/src/components/autocomplete-dropdown.tsx b/packages/desktop/src/components/autocomplete-dropdown.tsx new file mode 100644 index 0000000000..726125adf3 --- /dev/null +++ b/packages/desktop/src/components/autocomplete-dropdown.tsx @@ -0,0 +1,99 @@ +import { createEffect, Show, For, onMount, onCleanup } from "solid-js" +import { FileIcon, Icon } from "@/ui" +import { createList } from "solid-list" + +export interface AutocompleteItem { + type: "file" | "command" + label: string + value: string + description?: string +} + +interface AutocompleteDropdownProps { + items: AutocompleteItem[] + position: { top: number; left: number } + onSelect: (item: AutocompleteItem) => void + onClose: () => void +} + +export function AutocompleteDropdown(props: AutocompleteDropdownProps) { + let containerRef: HTMLDivElement | undefined + + const list = createList({ + items: () => props.items.map((item) => item.value), + initialActive: props.items[0]?.value, + loop: true, + }) + + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === "Escape") { + e.preventDefault() + e.stopPropagation() + props.onClose() + } else if (e.key === "Enter" || e.key === "Tab") { + e.preventDefault() + e.stopPropagation() + const selected = props.items.find((x) => x.value === list.active()) + if (selected) props.onSelect(selected) + } else if (e.key === "ArrowUp" || e.key === "ArrowDown") { + e.preventDefault() + e.stopPropagation() + list.onKeyDown(e) + } + } + + onMount(() => { + document.addEventListener("keydown", handleKeyDown, { capture: true }) + }) + + onCleanup(() => { + document.removeEventListener("keydown", handleKeyDown, { capture: true }) + }) + + createEffect(() => { + if (props.items.length > 0 && !props.items.find((x) => x.value === list.active())) { + list.setActive(props.items[0].value) + } + }) + + return ( + 0}> +
+ + {(item) => ( + + )} + +
+
+ ) +} diff --git a/packages/desktop/src/components/code.tsx b/packages/desktop/src/components/code.tsx index 40a40aa9a6..ea7ca1a988 100644 --- a/packages/desktop/src/components/code.tsx +++ b/packages/desktop/src/components/code.tsx @@ -330,9 +330,13 @@ export function Code(props: Props) { container = el }} innerHTML={html()} + style={{ + transform: "translateZ(0)", + "will-change": "contents", + }} class=" font-mono text-xs tracking-wide overflow-y-auto h-full - [&]:[counter-reset:line] + [&_code]:[counter-reset:line] [&_pre]:focus-visible:outline-none [&_pre]:overflow-x-auto [&_pre]:no-scrollbar [&_code]:min-w-full [&_code]:inline-block @@ -347,7 +351,7 @@ export function Code(props: Props) { [&_.line]:inline-block [&_.line]:w-full [&_.line]:hover:bg-background-element [&_.line::before]:sticky [&_.line::before]:left-0 - [&_.line::before]:w-12 [&_.line::before]:pr-4 + [&_.line::before]:w-10 [&_.line::before]:pr-4 [&_.line::before]:z-10 [&_.line::before]:bg-background-panel [&_.line::before]:text-text-muted/60 @@ -355,12 +359,11 @@ export function Code(props: Props) { [&_.line::before]:select-none [&_.line::before]:[counter-increment:line] [&_.line::before]:content-[counter(line)] + [&_.line::before]:min-w-[2ch] [&_.line-number-highlight]:bg-accent/20 [&_.line-number-highlight::before]:bg-accent/40! [&_.line-number-highlight::before]:text-background-panel! - [&_code.code-diff_.line::before]:content-[''] - [&_code.code-diff_.line::before]:w-0 - [&_code.code-diff_.line::before]:pr-0 + [&_code.code-diff_.line::before]:hidden [&_.diff-split_code.code-diff::before]:w-10 [&_.diff-split_.diff-newln]:left-0 [&_.diff-oldln]:sticky [&_.diff-oldln]:left-0 diff --git a/packages/desktop/src/components/drawer.tsx b/packages/desktop/src/components/drawer.tsx new file mode 100644 index 0000000000..5b26aef709 --- /dev/null +++ b/packages/desktop/src/components/drawer.tsx @@ -0,0 +1,63 @@ +import { Show, type ParentProps, onMount, onCleanup } from "solid-js" +import { Icon, IconButton } from "@/ui" + +interface DrawerProps extends ParentProps { + open: boolean + onClose: () => void + title: string + side?: "left" | "right" +} + +export default function Drawer(props: DrawerProps) { + let drawerRef: HTMLDivElement | undefined + + const handleBackdropClick = (e: MouseEvent) => { + if (e.target === e.currentTarget) { + props.onClose() + } + } + + onMount(() => { + const handleEscape = (e: KeyboardEvent) => { + if (e.key === "Escape" && props.open) { + props.onClose() + } + } + document.addEventListener("keydown", handleEscape) + onCleanup(() => document.removeEventListener("keydown", handleEscape)) + }) + + return ( + +
+
+
+

{props.title}

+ + + +
+
{props.children}
+
+
+
+ ) +} diff --git a/packages/desktop/src/components/editor-pane.tsx b/packages/desktop/src/components/editor-pane.tsx index 2f4c87e25f..4f59ecf8b4 100644 --- a/packages/desktop/src/components/editor-pane.tsx +++ b/packages/desktop/src/components/editor-pane.tsx @@ -1,4 +1,4 @@ -import { For, Match, Show, Switch, createSignal, splitProps } from "solid-js" +import { For, Match, Show, Switch, createSignal, splitProps, createMemo } from "solid-js" import { Tabs } from "@/ui/tabs" import { FileIcon, Icon, IconButton, Logo, Tooltip } from "@/ui" import { @@ -13,16 +13,40 @@ import { import type { DragEvent, Transformer } from "@thisbeyond/solid-dnd" import type { LocalFile } from "@/context/local" import { Code } from "@/components/code" -import { useLocal } from "@/context" +import PromptForm from "@/components/prompt-form" +import SuggestionChips from "@/components/suggestion-chips" +import { useLocal, useSDK, useSync } from "@/context" +import { getFilename } from "@/utils" import type { JSX } from "solid-js" interface EditorPaneProps { + layoutKey: string + timelinePane: string onFileClick: (file: LocalFile) => void + onOpenModelSelect: () => void + onOpenAgentSelect: () => void + onInputRefChange: (element: HTMLTextAreaElement | null) => void + onPromptSubmit: (prompt: string) => void + onDragProximity?: (proximity: { isDragging: boolean; nearDockZone: boolean; x: number; y: number }) => void + onDrop?: () => void + hideFloatingChat?: boolean } export default function EditorPane(props: EditorPaneProps): JSX.Element { - const [localProps] = splitProps(props, ["onFileClick"]) + const [localProps] = splitProps(props, [ + "layoutKey", + "timelinePane", + "onFileClick", + "onOpenModelSelect", + "onOpenAgentSelect", + "onInputRefChange", + "onPromptSubmit", + "onDragProximity", + "onDrop", + "hideFloatingChat", + ]) const local = useLocal() + const sync = useSync() const [activeItem, setActiveItem] = createSignal(undefined) const navigateChange = (dir: 1 | -1) => { @@ -63,8 +87,133 @@ export default function EditorPane(props: EditorPaneProps): JSX.Element { setActiveItem(undefined) } + const handleOpenFolder = () => { + const input = document.createElement("input") + input.type = "file" + input.webkitdirectory = true + input.onchange = (e) => { + const files = (e.target as HTMLInputElement).files + if (files && files.length > 0) { + const path = files[0].webkitRelativePath.split("/")[0] + window.location.href = `/?path=${encodeURIComponent(path)}` + } + } + input.click() + } + + const suggestions = createMemo(() => { + if (local.file.opened().length > 0) return [] + + const hasFiles = Object.keys(sync.data.node).length > 0 + if (!hasFiles) { + return ["Open a folder to get started"] + } + + const activeSession = local.session.active() + const hasConversation = activeSession && sync.data.message[activeSession.id]?.length > 0 + + if (hasConversation) { + const messages = sync.data.message[activeSession.id] || [] + + const conversationText = messages + .map((m) => + sync.data.part[m.id] + ?.filter((p) => p.type === "text") + .map((p) => p.text) + .join(" "), + ) + .join(" ") + .toLowerCase() + + const result = [] + + if (conversationText.includes("agent") || conversationText.includes("guideline")) { + result.push("Review the AGENTS.md file") + result.push("What build commands are configured?") + } + + if (conversationText.includes("component") || conversationText.includes("ui")) { + result.push("Show me all components") + result.push("Create a new component") + } + + if (conversationText.includes("test") || conversationText.includes("spec")) { + result.push("Write tests for this feature") + result.push("Run the test suite") + } + + if ( + conversationText.includes("style") || + conversationText.includes("css") || + conversationText.includes("theme") + ) { + result.push("Update the theme system") + result.push("Review styling patterns") + } + + if (conversationText.includes("error") || conversationText.includes("bug") || conversationText.includes("fix")) { + result.push("Debug this issue") + result.push("Check error logs") + } + + if (result.length === 0) { + result.push("Continue working on this feature") + result.push("What should we do next?") + result.push("Review recent changes") + } + + return result.slice(0, 6) + } + + const files = Object.keys(sync.data.node) + const agentsMdFile = files.find((f) => f.endsWith("AGENTS.md") || f.endsWith("agents.md")) + const hasAgentsMd = !!agentsMdFile + const hasPackageJson = files.some((f) => f.endsWith("package.json")) + const hasReadme = files.some((f) => f.toLowerCase().includes("readme")) + const hasSrc = files.some((f) => f.startsWith("src/")) + const hasTests = files.some((f) => f.includes("test") || f.includes("spec")) + const hasTsConfig = files.some((f) => f.includes("tsconfig")) + const hasComponents = files.some((f) => f.includes("component")) + + const result = [] + + if (!hasAgentsMd) { + result.push("Create an AGENTS.md file for this project") + } else { + result.push("Review the AGENTS.md file") + } + if (hasReadme) result.push("Explain what this project does") + if (hasPackageJson) result.push("Show me the dependencies") + if (hasSrc) result.push("Give me an overview of the codebase") + if (hasComponents) result.push("Review component architecture") + if (hasTsConfig) result.push("Check TypeScript configuration") + if (hasTests) result.push("Review test coverage") + + if (result.length === 0) { + result.push("Explain the project structure") + } + + return result.slice(0, 6) + }) + + const handleSuggestion = async (suggestion: string) => { + if (suggestion === "Open a folder to get started") { + handleOpenFolder() + } else { + await handlePromptSubmit(suggestion) + } + } + return (
+ +
+ +
+ +
+
+
navigateChange(-1)}> - + navigateChange(1)}> - +
@@ -120,7 +269,7 @@ export default function EditorPane(props: EditorPaneProps): JSX.Element { }} onClick={() => local.file.setView(activeFile.path, "raw")} > - + @@ -134,7 +283,7 @@ export default function EditorPane(props: EditorPaneProps): JSX.Element { }} onClick={() => local.file.setView(activeFile.path, "diff-unified")} > - + @@ -148,19 +297,66 @@ export default function EditorPane(props: EditorPaneProps): JSX.Element { }} onClick={() => local.file.setView(activeFile.path, "diff-split")} > - + ) })()} + + local.layout.toggle(localProps.layoutKey, localProps.timelinePane)} + > + + + {(file) => ( {(() => { + const ext = file.path.split(".").pop()?.toLowerCase() + const imageExts = ["png", "jpg", "jpeg", "gif", "svg", "webp", "bmp", "ico"] + const isImage = ext && imageExts.includes(ext) + + if (isImage) { + const absolutePath = sync.absolute(file.path) + + return ( +
+
+ {file.name} { + const target = e.currentTarget + target.style.display = "none" + const sibling = target.nextElementSibling as HTMLElement + if (sibling) sibling.style.display = "block" + }} + /> + +
+
+ ) + } + const view = local.file.view(file.path) const showRaw = view === "raw" || !file.content?.diff const code = showRaw ? (file.content?.content ?? "") : (file.content?.diff ?? "") @@ -184,6 +380,21 @@ export default function EditorPane(props: EditorPaneProps): JSX.Element { })()} + + localProps.onInputRefChange(element ?? null)} + onDragProximity={localProps.onDragProximity} + onDrop={localProps.onDrop} + /> + ) } @@ -233,7 +444,7 @@ function SortableTab(props: { variant="ghost" onClick={() => props.onTabClose(props.file)} > - + diff --git a/packages/desktop/src/components/file-tree.tsx b/packages/desktop/src/components/file-tree.tsx index d31255ced5..0eee63c73c 100644 --- a/packages/desktop/src/components/file-tree.tsx +++ b/packages/desktop/src/components/file-tree.tsx @@ -1,6 +1,6 @@ import { useLocal } from "@/context" import type { LocalFile } from "@/context/local" -import { Collapsible, FileIcon, Tooltip } from "@/ui" +import { Collapsible, FileIcon } from "@/ui" import { For, Match, Switch, Show, type ComponentProps, type ParentProps } from "solid-js" import { Dynamic } from "solid-js/web" @@ -19,6 +19,7 @@ export default function FileTree(props: { component={p.as ?? "div"} classList={{ "p-0.5 w-full flex items-center gap-x-2 hover:bg-background-element cursor-pointer": true, + "!py-0": p.node.type === "directory", "bg-background-element": local.file.active()?.path === p.node.path, [props.nodeClass ?? ""]: !!props.nodeClass, }} @@ -71,38 +72,36 @@ export default function FileTree(props: {
{(node) => ( - - - - (open ? local.file.expand(node.path) : local.file.collapse(node.path))} - > - - - - - - - - - - - - - props.onFileClick?.(node)}> -
- - - - - + + + (open ? local.file.expand(node.path) : local.file.collapse(node.path))} + > + + + + + + + + + + + + + props.onFileClick?.(node)} title={node.path}> +
+ + + + )}
diff --git a/packages/desktop/src/components/markdown.tsx b/packages/desktop/src/components/markdown.tsx index a60fad1492..9a0cfa97b2 100644 --- a/packages/desktop/src/components/markdown.tsx +++ b/packages/desktop/src/components/markdown.tsx @@ -18,6 +18,11 @@ export function Markdown(props: { text: string; class?: string }) {
) } diff --git a/packages/desktop/src/components/mobile-header.tsx b/packages/desktop/src/components/mobile-header.tsx new file mode 100644 index 0000000000..bdc5ba749d --- /dev/null +++ b/packages/desktop/src/components/mobile-header.tsx @@ -0,0 +1,54 @@ +import { Icon, IconButton } from "@/ui" +import { Show } from "solid-js" + +interface MobileHeaderProps { + title: string + showBack?: boolean + onBack?: () => void + onMenuClick?: () => void + actions?: Array<{ + icon: string + label: string + onClick: () => void + }> +} + +export default function MobileHeader(props: MobileHeaderProps) { + return ( +
+
+
+ + + + + + } + > + + + + +

{props.title}

+
+ +
+ {props.actions?.map((action) => ( + + + + ))} +
+
+
+
+ ) +} diff --git a/packages/desktop/src/components/mobile-layout.tsx b/packages/desktop/src/components/mobile-layout.tsx new file mode 100644 index 0000000000..9f937f9571 --- /dev/null +++ b/packages/desktop/src/components/mobile-layout.tsx @@ -0,0 +1,308 @@ +import { createSignal, For, Match, Show, Switch, onMount, onCleanup, createMemo } from "solid-js" +import { FileIcon, Logo } from "@/ui" +import { Tabs } from "@/ui/tabs" +import FileTree from "@/components/file-tree" +import SessionList from "@/components/session-list" +import SessionTimeline from "@/components/session-timeline" +import PromptForm from "@/components/prompt-form" +import SuggestionChips from "@/components/suggestion-chips" +import MobileNavigation, { type MobileTab } from "@/components/mobile-navigation" +import MobileHeader from "@/components/mobile-header" +import Drawer from "@/components/drawer" +import EditorPane from "@/components/editor-pane" +import { useLocal, useSync } from "@/context" +import type { LocalFile } from "@/context/local" +import { getDirectory, getFilename, createSwipeGesture, vibrate } from "@/utils" + +interface MobileLayoutProps { + layoutKey: string + timelinePane: string + onFileClick: (file: LocalFile) => void + onPromptSubmit: (prompt: string) => Promise + onOpenModelSelect: () => void + onOpenAgentSelect: () => void +} + +export default function MobileLayout(props: MobileLayoutProps) { + const local = useLocal() + const sync = useSync() + const [activeTab, setActiveTab] = createSignal("editor") + const [drawerOpen, setDrawerOpen] = createSignal(false) + const [keyboardHeight, setKeyboardHeight] = createSignal(0) + const [viewportHeight, setViewportHeight] = createSignal(typeof window !== "undefined" ? window.innerHeight : 0) + + const suggestions = createMemo(() => { + const hasFiles = Object.keys(sync.data.node).length > 0 + if (!hasFiles) { + return ["Open a folder to get started"] + } + + const files = Object.keys(sync.data.node) + const agentsMdFile = files.find((f) => f.endsWith("AGENTS.md") || f.endsWith("agents.md")) + const hasAgentsMd = !!agentsMdFile + const hasPackageJson = files.some((f) => f.endsWith("package.json")) + const hasReadme = files.some((f) => f.toLowerCase().includes("readme")) + + const result = [] + + if (!hasAgentsMd) { + result.push("Create an AGENTS.md file") + } else { + result.push("Review AGENTS.md") + } + + if (hasPackageJson) { + result.push("What build commands are configured?") + } + + if (hasReadme) { + result.push("Summarize this project") + } + + result.push("Show me all components") + result.push("Create a new feature") + result.push("Write tests") + + return result.slice(0, 6) + }) + + const handleSuggestion = async (suggestion: string) => { + await props.onPromptSubmit(suggestion) + setActiveTab("chat") + } + + const handleSwipeLeft = () => { + const tabs: MobileTab[] = ["files", "editor", "chat"] + const currentIndex = tabs.indexOf(activeTab()) + if (currentIndex < tabs.length - 1) { + vibrate(10) + setActiveTab(tabs[currentIndex + 1]) + } + } + + const handleSwipeRight = () => { + const tabs: MobileTab[] = ["files", "editor", "chat"] + const currentIndex = tabs.indexOf(activeTab()) + if (currentIndex > 0) { + vibrate(10) + setActiveTab(tabs[currentIndex - 1]) + } + } + + let containerRef: HTMLDivElement | undefined + + onMount(() => { + const handleResize = () => { + const newHeight = window.innerHeight + const heightDiff = viewportHeight() - newHeight + if (heightDiff > 100) { + setKeyboardHeight(heightDiff) + } else { + setKeyboardHeight(0) + } + setViewportHeight(newHeight) + } + + const handleVisualViewportResize = () => { + if (window.visualViewport) { + const keyboardOffset = window.innerHeight - window.visualViewport.height + setKeyboardHeight(keyboardOffset > 100 ? keyboardOffset : 0) + } + } + + window.addEventListener("resize", handleResize) + window.visualViewport?.addEventListener("resize", handleVisualViewportResize) + + if (containerRef) { + const cleanupSwipe = createSwipeGesture(containerRef, { + onSwipeLeft: handleSwipeLeft, + onSwipeRight: handleSwipeRight, + }) + + onCleanup(() => { + cleanupSwipe() + }) + } + + onCleanup(() => { + window.removeEventListener("resize", handleResize) + window.visualViewport?.removeEventListener("resize", handleVisualViewportResize) + }) + }) + + return ( +
0 ? `calc(100vh - ${keyboardHeight()}px)` : "100vh", + "padding-bottom": keyboardHeight() > 0 ? "0" : "calc(4rem + var(--safe-area-inset-bottom))", + "touch-action": "pan-y", + }} + > + + + setDrawerOpen(true)} /> +
+ + + + Files + + + Changes + + + + + + + No changes
} + > +
    + + {(path) => ( +
  • + +
  • + )} +
    +
+ + + +
+ + + + setDrawerOpen(true)} + /> +
+ +
+
+
+ +

Start a conversation or open a file to begin

+
+
+ +
+ +
+
+
+ +
+ {}} + hideFloatingChat={true} + /> +
+
+
+
+ + + + setDrawerOpen(true)} /> +
+ +
+ + } + > + {(activeSession) => ( + <> + local.session.clearActive()} + /> +
+ +
+
0 ? `${keyboardHeight()}px` : "calc(4rem + var(--safe-area-inset-bottom))", + }} + > +
+ +
+
+ + )} +
+
+ + + + + setDrawerOpen(false)} title="Settings" side="left"> +
+
+

Agent

+ +
+
+

Model

+ +
+
+
+
+ ) +} diff --git a/packages/desktop/src/components/mobile-navigation.tsx b/packages/desktop/src/components/mobile-navigation.tsx new file mode 100644 index 0000000000..434d4f5303 --- /dev/null +++ b/packages/desktop/src/components/mobile-navigation.tsx @@ -0,0 +1,65 @@ +import { Icon } from "@/ui" +import { Show } from "solid-js" + +export type MobileTab = "files" | "editor" | "chat" + +interface MobileNavigationProps { + activeTab: MobileTab + onTabChange: (tab: MobileTab) => void + hasActiveSession: boolean +} + +export default function MobileNavigation(props: MobileNavigationProps) { + return ( + + ) +} diff --git a/packages/desktop/src/components/prompt-form.tsx b/packages/desktop/src/components/prompt-form.tsx index 5e6441596c..3083c89549 100644 --- a/packages/desktop/src/components/prompt-form.tsx +++ b/packages/desktop/src/components/prompt-form.tsx @@ -1,31 +1,31 @@ -import { For, Show, createMemo, onCleanup, type JSX } from "solid-js" +import { For, Show, createEffect, createMemo, createSignal, onCleanup, onMount, createResource } from "solid-js" import { createStore } from "solid-js/store" -import { Popover } from "@kobalte/core/popover" import { Button, FileIcon, Icon, IconButton, Tooltip } from "@/ui" import { Select } from "@/components/select" -import { useLocal } from "@/context" +import { useLocal, useMobile } from "@/context" import type { FileContext, LocalFile } from "@/context/local" -import { getDirectory, getFilename } from "@/utils" -import { composeDisplaySegments, createAttachmentDisplay, parsePrompt, registerCandidate } from "./prompt-form-helpers" -import type { - AttachmentCandidate, - PromptAttachmentPart, - PromptAttachmentSegment, - PromptDisplaySegment, - PromptSubmitValue, -} from "./prompt-form-helpers" -import { useMentionController, usePromptScrollSync, usePromptSpeech, type PromptFormState } from "./prompt-form-hooks" +import { getFilename, getDirectory } from "@/utils" +import { createSpeechRecognition } from "@/utils/speech" +import { getCurrentWindow } from "@tauri-apps/api/window" +import { AutocompleteDropdown, type AutocompleteItem } from "@/components/autocomplete-dropdown" +import { usePromptSpeech, useMentionController, usePromptScrollSync, type PromptFormState } from "./prompt-form-hooks" +import { parsePrompt, createAttachmentDisplay, type PromptAttachmentSegment } from "./prompt-form-helpers" interface PromptFormProps { class?: string classList?: Record onSubmit: (prompt: PromptSubmitValue) => Promise | void onOpenModelSelect: () => void + onOpenAgentSelect: () => void onInputRefChange?: (element: HTMLTextAreaElement | undefined) => void + onDragProximity?: (proximity: { isDragging: boolean; nearDockZone: boolean; x: number; y: number }) => void + onDrop?: () => void + docked?: boolean } export default function PromptForm(props: PromptFormProps) { const local = useLocal() + const mobile = useMobile() const [state, setState] = createStore({ promptInput: "", @@ -35,9 +35,57 @@ export default function PromptForm(props: PromptFormProps) { mentionRange: undefined, mentionIndex: 0, mentionAnchorOffset: { x: 0, y: 0 }, - inlineAliases: new Map(), + inlineAliases: new Map(), }) + const [prompt, setPrompt] = createSignal("") + const [isDragOver, setIsDragOver] = createSignal(false) + const [uploadedFiles, setUploadedFiles] = createSignal([]) + const [autocomplete, setAutocomplete] = createSignal<{ + type: "file" | "command" + query: string + position: { top: number; left: number } + startPos: number + } | null>(null) + + const [autocompleteItems] = createResource(autocomplete, async (ac) => { + if (!ac) return [] + + if (ac.type === "file") { + const files = await local.file.search(ac.query) + + const sorted = files.sort((a: string, b: string) => { + const aFilename = getFilename(a) + const bFilename = getFilename(b) + const aIsHidden = aFilename.startsWith(".") + const bIsHidden = bFilename.startsWith(".") + + if (aIsHidden && !bIsHidden) return 1 + if (!aIsHidden && bIsHidden) return -1 + return 0 + }) + + return sorted.slice(0, 10).map((path: string) => ({ + type: "file" as const, + label: getFilename(path), + value: path, + description: getDirectory(path), + })) + } + + if (ac.type === "command") { + const commands = [ + { label: "model", value: "model", description: "Change model" }, + { label: "agent", value: "agent", description: "Change agent" }, + ] + return commands.filter((c) => c.label.startsWith(ac.query)).map((c) => ({ type: "command" as const, ...c })) + } + + return [] + }) + + let dragCounter = 0 + const placeholderText = "Start typing or speaking..." const { @@ -50,7 +98,51 @@ export default function PromptForm(props: PromptFormProps) { let inputRef: HTMLTextAreaElement | undefined = undefined let overlayContainerRef: HTMLDivElement | undefined = undefined - let mentionMeasureRef: HTMLDivElement | undefined = undefined + let containerRef!: HTMLDivElement + let shouldAutoScroll = true + let isDraggingForm = false + let dragStartPos = { x: 0, y: 0 } + let currentTranslate = { x: 0, y: 0 } + let animationFrameId: number | undefined + let wasNearDockZone = false + + const modeColors = createMemo(() => { + const agentName = local.agent.current().name.toLowerCase() + + if (agentName === "build") { + return { + ring: "ring-primary/50", + focusRing: "focus-within:ring-primary/40", + focusBorder: "focus-within:border-primary", + button: "bg-primary", + buttonHover: "hover:bg-primary/90", + } + } else if (agentName === "plan") { + return { + ring: "ring-secondary/50", + focusRing: "focus-within:ring-secondary/40", + focusBorder: "focus-within:border-secondary", + button: "bg-secondary", + buttonHover: "hover:bg-secondary/90", + } + } else if (agentName === "docs") { + return { + ring: "ring-accent/50", + focusRing: "focus-within:ring-accent/40", + focusBorder: "focus-within:border-accent", + button: "bg-accent", + buttonHover: "hover:bg-accent/90", + } + } + + return { + ring: "ring-border-active/50", + focusRing: "focus-within:ring-primary/40", + focusBorder: "focus-within:border-primary", + button: "bg-primary", + buttonHover: "hover:bg-primary/90", + } + }) const attachmentLookup = createMemo(() => { const map = new Map() @@ -127,74 +219,77 @@ export default function PromptForm(props: PromptFormProps) { getActiveContext: () => local.context.active() ?? undefined, }) - const { handlePromptScroll, resetScrollPosition } = usePromptScrollSync({ + const { handlePromptScroll, resetScrollPosition, setAutoScroll } = usePromptScrollSync({ state, getInputRef: () => inputRef, getOverlayRef: () => overlayContainerRef, - interim: () => (isRecording() ? interimTranscript() : ""), + interim: interimTranscript, updateMentionPosition, }) - const displaySegments = createMemo(() => { - const value = state.promptInput - const segments = parsedPrompt().segments - const interim = isRecording() ? interimTranscript() : "" - return composeDisplaySegments(segments, value, interim) - }) + let mentionMeasureRef: HTMLDivElement | undefined = undefined + function renderAttachmentChip(part: PromptAttachmentPart, _placeholder: string) { + const display = part.display ?? createAttachmentDisplay(part.path, part.selection) + return @{display} + } + + function renderTextSegment(text: string) { + return {text} + } + + const displaySegments = createMemo(() => parsedPrompt().segments) const hasDisplaySegments = createMemo(() => displaySegments().length > 0) - function handleAttachmentNavigation( - event: KeyboardEvent & { currentTarget: HTMLTextAreaElement }, - direction: "left" | "right", - ) { - const element = event.currentTarget - const caret = element.selectionStart ?? 0 - const segments = attachmentSegments() - if (direction === "left") { - let match = segments.find((segment) => caret > segment.start && caret <= segment.end) - if (!match && element.selectionStart !== element.selectionEnd) { - match = segments.find( - (segment) => element.selectionStart === segment.start && element.selectionEnd === segment.end, - ) - } - if (!match) return false - event.preventDefault() - if (element.selectionStart === match.start && element.selectionEnd === match.end) { - const next = Math.max(0, match.start) - element.setSelectionRange(next, next) - syncMentionFromCaret(element) - return true - } - element.setSelectionRange(match.start, match.end) - syncMentionFromCaret(element) - return true - } - if (direction === "right") { - let match = segments.find((segment) => caret >= segment.start && caret < segment.end) - if (!match && element.selectionStart !== element.selectionEnd) { - match = segments.find( - (segment) => element.selectionStart === segment.start && element.selectionEnd === segment.end, - ) - } - if (!match) return false - event.preventDefault() - if (element.selectionStart === match.start && element.selectionEnd === match.end) { - const next = match.end - element.setSelectionRange(next, next) - syncMentionFromCaret(element) - return true - } - element.setSelectionRange(match.start, match.end) - syncMentionFromCaret(element) - return true - } - return false + function PromptDisplayOverlay(props: any) { + return ( +
+ {props.placeholder}}> + + {(segment: any) => ( + {segment.text}} + > + {props.renderAttachmentChip ? props.renderAttachmentChip(segment, props.placeholder) : @{segment.token}} + + )} + + +
+ ) } - function renderAttachmentChip(part: PromptAttachmentPart, _placeholder: string) { - const display = part.display ?? createAttachmentDisplay(part.path, part.selection) - return @{display} + function MentionSuggestions(props: any) { + return ( + +
+ + {(item: string, index) => ( + + )} + + }> +
Loading...
+
+
+
+ ) } function renderTextSegment(value: string) { @@ -235,6 +330,98 @@ export default function PromptForm(props: PromptFormProps) { } } + const getCaretCoordinates = (element: HTMLTextAreaElement): { top: number; left: number } => { + const rect = element.getBoundingClientRect() + const style = window.getComputedStyle(element) + const lineHeight = parseInt(style.lineHeight || "20") + + return { + top: rect.top + lineHeight + 5, + left: rect.left + 10, + } + } + + const detectAutocomplete = (value: string, cursorPos: number) => { + const beforeCursor = value.slice(0, cursorPos) + + const atMatch = beforeCursor.match(/@(\S*)$/) + if (atMatch) { + const query = atMatch[1] + const startPos = cursorPos - atMatch[0].length + const position = getCaretCoordinates(inputRef!) + + setAutocomplete({ + type: "file", + query, + position, + startPos, + }) + return + } + + const slashMatch = value.match(/^\/(\w*)$/) + if (slashMatch && cursorPos <= slashMatch[0].length) { + const query = slashMatch[1] + const position = getCaretCoordinates(inputRef!) + + setAutocomplete({ + type: "command", + query, + position, + startPos: 0, + }) + return + } + + setAutocomplete(null) + } + + const handleAutocompleteSelect = (item: AutocompleteItem) => { + if (!autocomplete() || !inputRef) return + + const ac = autocomplete()! + const currentPrompt = prompt() + const before = currentPrompt.slice(0, ac.startPos) + const after = currentPrompt.slice(inputRef.selectionStart) + + if (ac.type === "file") { + const newPrompt = before + "@" + item.label + " " + after + setPrompt(newPrompt) + + local.context.add({ + type: "file", + path: item.value, + }) + + const newCursorPos = before.length + item.label.length + 2 + queueMicrotask(() => { + if (inputRef) { + inputRef.selectionStart = newCursorPos + inputRef.selectionEnd = newCursorPos + } + }) + } else if (ac.type === "command") { + const newPrompt = before + after + setPrompt(newPrompt) + + if (item.value === "model") { + props.onOpenModelSelect() + } else if (item.value === "agent") { + props.onOpenAgentSelect() + } + + queueMicrotask(() => { + if (inputRef) { + inputRef.selectionStart = before.length + inputRef.selectionEnd = before.length + } + }) + } + + setAutocomplete(null) + inputRef?.focus() + } + const handleSubmit = async (event: SubmitEvent) => { event.preventDefault() const parts = baseParts() @@ -258,37 +445,194 @@ export default function PromptForm(props: PromptFormProps) { await props.onSubmit(currentPrompt) } + const handleDragStart = (event: MouseEvent) => { + if (props.docked) return + const target = event.target as HTMLElement + if ( + target.closest("textarea") || + target.closest("button") || + target.closest("input") || + target.closest("[role='combobox']") || + target.closest("[role='listbox']") + ) + return + + isDraggingForm = true + dragStartPos = { x: event.clientX - currentTranslate.x, y: event.clientY - currentTranslate.y } + containerRef.style.cursor = "grabbing" + event.preventDefault() + } + + const handleDragMove = (event: MouseEvent) => { + if (!isDraggingForm) return + event.preventDefault() + + if (animationFrameId) return + + animationFrameId = requestAnimationFrame(() => { + currentTranslate = { + x: event.clientX - dragStartPos.x, + y: event.clientY - dragStartPos.y, + } + containerRef.style.transform = `translate3d(${currentTranslate.x}px, ${currentTranslate.y}px, 0)` + + const windowWidth = window.innerWidth + const windowHeight = window.innerHeight + const isNearRight = event.clientX > windowWidth * 0.75 + const isNearBottom = event.clientY > windowHeight * 0.6 + const nearDockZone = isNearRight && isNearBottom + + wasNearDockZone = nearDockZone + + props.onDragProximity?.({ + isDragging: true, + nearDockZone, + x: event.clientX, + y: event.clientY, + }) + + props.onDragProximity?.({ + isDragging: true, + nearDockZone, + x: event.clientX, + y: event.clientY, + }) + + animationFrameId = undefined + }) + } + + const handleDragEnd = (event: MouseEvent) => { + if (!isDraggingForm) return + + console.log("[PromptForm handleDragEnd]", { + clientX: event.clientX, + clientY: event.clientY, + windowWidth: window.innerWidth, + windowHeight: window.innerHeight, + wasNearDockZone, + }) + + isDraggingForm = false + containerRef.style.cursor = "" + + if (wasNearDockZone) { + console.log("[PromptForm] Was near dock zone, calling onDrop") + props.onDrop?.() + } + + currentTranslate = { x: 0, y: 0 } + containerRef.style.transform = `translate3d(0px, 0px, 0)` + + wasNearDockZone = false + + props.onDragProximity?.({ + isDragging: false, + nearDockZone: false, + x: 0, + y: 0, + }) + } + + onMount(async () => { + document.addEventListener("mousemove", handleDragMove) + document.addEventListener("mouseup", handleDragEnd) + + // Only set up Tauri drag/drop in desktop environment + if (typeof window !== "undefined" && "__TAURI__" in window) { + try { + const tauriWindow = getCurrentWindow() + if (tauriWindow) { + const unlisten = await tauriWindow.onDragDropEvent((e) => { + switch (e.payload.type) { + case "enter": + dragCounter++ + setIsDragOver(true) + break + case "over": + break + case "drop": + dragCounter = 0 + setIsDragOver(false) + if (e.payload.paths && e.payload.paths.length > 0) { + const current = uploadedFiles() + const available = 5 - current.length + if (available <= 0) return + Promise.all( + e.payload.paths.slice(0, available).map(async (path) => { + const response = await fetch(`asset://localhost${path}`) + const blob = await response.blob() + const fileName = path.split("/").pop() || "file" + return new File([blob], fileName, { type: blob.type }) + }), + ).then((files) => { + setUploadedFiles([...current, ...files]) + }) + } + break + case "leave": + dragCounter-- + if (dragCounter === 0) { + setIsDragOver(false) + } + break + } + }) + + onCleanup(() => { + unlisten() + }) + } + } catch (error) { + console.warn("[PromptForm] Tauri drag/drop not available:", error) + } + } + }) + onCleanup(() => { + document.removeEventListener("mousemove", handleDragMove) + document.removeEventListener("mouseup", handleDragEnd) + if (animationFrameId) cancelAnimationFrame(animationFrameId) props.onInputRefChange?.(undefined) }) return (
{ const evt = event as unknown as globalThis.DragEvent - if (evt.dataTransfer?.types.includes("text/plain")) { + dragCounter++ + if (evt.dataTransfer?.types.includes("text/plain") || evt.dataTransfer?.types.includes("Files")) { evt.preventDefault() setState("isDragOver", true) } }} - onDragLeave={(event) => { - if (event.currentTarget === event.target) { - setState("isDragOver", false) + onDragLeave={() => { + dragCounter-- + if (dragCounter === 0) { + setIsDragOver(false) } }} onDragOver={(event) => { const evt = event as unknown as globalThis.DragEvent - if (evt.dataTransfer?.types.includes("text/plain")) { + if (evt.dataTransfer?.types.includes("text/plain") || evt.dataTransfer?.types.includes("Files")) { evt.preventDefault() evt.dataTransfer.dropEffect = "copy" } @@ -296,7 +640,8 @@ export default function PromptForm(props: PromptFormProps) { onDrop={(event) => { const evt = event as unknown as globalThis.DragEvent evt.preventDefault() - setState("isDragOver", false) + dragCounter = 0 + setIsDragOver(false) const data = evt.dataTransfer?.getData("text/plain") if (data && data.startsWith("file:")) { @@ -308,10 +653,20 @@ export default function PromptForm(props: PromptFormProps) { path: filePath, }) } + return + } + + const files = evt.dataTransfer?.files + if (files && files.length > 0) { + const current = uploadedFiles() + const available = 5 - current.length + if (available <= 0) return + const newFiles = Array.from(files).slice(0, available) + setUploadedFiles([...current, ...newFiles]) } }} > - 0 || local.context.active()}> + 0 || local.context.active() || uploadedFiles().length > 0}>
local.context.removeActive()} /> @@ -319,6 +674,14 @@ export default function PromptForm(props: PromptFormProps) { {(file) => local.context.remove(file.key)} />} + + {(file, idx) => ( + setUploadedFiles((prev) => prev.filter((_, i) => i !== idx()))} + /> + )} +
@@ -327,23 +690,17 @@ export default function PromptForm(props: PromptFormProps) { inputRef = element ?? undefined props.onInputRefChange?.(inputRef) }} - value={state.promptInput} - onInput={handlePromptInput} + value={prompt()} + onInput={(event) => { + const value = event.currentTarget.value + const cursorPos = event.currentTarget.selectionStart + setPrompt(value) + detectAutocomplete(value, cursorPos) + }} onKeyDown={handlePromptKeyDown} - onClick={(event) => - queueMicrotask(() => { - syncMentionFromCaret(event.currentTarget) - }) - } - onSelect={(event) => - queueMicrotask(() => { - syncMentionFromCaret(event.currentTarget) - }) - } - onBlur={(event) => { - const next = event.relatedTarget as HTMLElement | null - if (next && next.closest('[data-mention-popover="true"]')) return - closeMention() + onKeyUp={(event) => { + const cursorPos = event.currentTarget.selectionStart + detectAutocomplete(prompt(), cursorPos) }} onScroll={handlePromptScroll} placeholder={placeholderText} @@ -351,7 +708,7 @@ export default function PromptForm(props: PromptFormProps) { autocomplete="off" autocorrect="off" spellcheck={false} - class="relative w-full h-20 rounded-md px-0.5 resize-none overflow-y-auto + class="relative w-full h-20 rounded-lg px-0.5 resize-none overflow-y-auto bg-transparent text-transparent caret-text font-light text-base leading-relaxed focus:outline-none selection:bg-primary/20" > @@ -393,14 +750,26 @@ export default function PromptForm(props: PromptFormProps) { current={local.agent.current().name} onSelect={local.agent.set} class="uppercase" + classList={{ + "text-primary": local.agent.current().name.toLowerCase() === "build", + "text-secondary": local.agent.current().name.toLowerCase() === "plan", + "text-accent": local.agent.current().name.toLowerCase() === "docs", + }} /> - {local.model.current()?.provider.name}
-
+
- + - - - + + { + const input = document.createElement("input") + input.type = "file" + input.multiple = true + input.accept = "image/*,application/pdf,.txt,.md,.json,.xml,.csv" + input.onchange = (e) => { + const files = (e.target as HTMLInputElement).files + if (files && files.length > 0) { + const current = uploadedFiles() + const available = 5 - current.length + if (available <= 0) return + const newFiles = Array.from(files).slice(0, available) + setUploadedFiles([...current, ...newFiles]) + } + } + input.click() + }} + > + + 0}> + + {uploadedFiles().length} + + + + - +
+ + setAutocomplete(null)} + /> +
) } @@ -446,7 +855,7 @@ const ActiveTabContextTag = (props: { file: LocalFile; onClose: () => void }) =>
@@ -462,7 +871,7 @@ const FileTag = (props: { file: FileContext; onClose: () => void }) => (
@@ -479,103 +888,19 @@ const FileTag = (props: { file: FileContext; onClose: () => void }) => (
) -function PromptDisplayOverlay(props: { - hasDisplaySegments: boolean - displaySegments: PromptDisplaySegment[] - placeholder: string - renderAttachmentChip: (part: PromptAttachmentPart, placeholder: string) => JSX.Element - renderTextSegment: (value: string) => JSX.Element | undefined -}) { - return ( -
- {props.placeholder}}> - - {(segment) => { - if (segment.kind === "text") { - return props.renderTextSegment(segment.value) - } - if (segment.kind === "attachment") { - return props.renderAttachmentChip(segment.part, segment.source) - } - return ( - - {segment.leadingSpace ? ` ${segment.value}` : segment.value} - - ) - }} - - +const UploadedFileTag = (props: { file: File; onClose: () => void }) => ( +
+ + + +
+ {props.file.name} + ({(props.file.size / 1024).toFixed(1)}KB)
- ) -} - -function MentionSuggestions(props: { - open: boolean - anchor: { x: number; y: number } - loading: boolean - items: string[] - activeIndex: number - onHover: (index: number) => void - onSelect: (path: string) => void -}) { - return ( - - - ) -} - -export type { - PromptAttachmentPart, - PromptAttachmentSegment, - PromptContentPart, - PromptDisplaySegment, - PromptSubmitValue, -} from "./prompt-form-helpers" +
+) diff --git a/packages/desktop/src/components/resizeable-pane.tsx b/packages/desktop/src/components/resizeable-pane.tsx index 49ccc4e701..e349a83719 100644 --- a/packages/desktop/src/components/resizeable-pane.tsx +++ b/packages/desktop/src/components/resizeable-pane.tsx @@ -195,6 +195,8 @@ export function ResizeablePane(props: ResizeablePaneProps) { style={{ width: `${width()}%`, flex: `0 0 ${width()}%`, + transform: "translateZ(0)", + "will-change": "width", }} > {props.children} diff --git a/packages/desktop/src/components/select-dialog.tsx b/packages/desktop/src/components/select-dialog.tsx index 315fe14e5f..7df4cdf5be 100644 --- a/packages/desktop/src/components/select-dialog.tsx +++ b/packages/desktop/src/components/select-dialog.tsx @@ -1,4 +1,4 @@ -import { createEffect, Show, For, createMemo, type JSX, createResource } from "solid-js" +import { createEffect, Show, For, createMemo, type JSX, createResource, onMount } from "solid-js" import { Dialog } from "@kobalte/core/dialog" import { Icon, IconButton } from "@/ui" import { createStore } from "solid-js/store" @@ -16,6 +16,9 @@ interface SelectDialogProps { groupBy?: (x: T) => string onSelect?: (value: T | undefined) => void onClose?: () => void + onBack?: () => void + reduceBlur?: boolean + keepOpen?: boolean } export function SelectDialog(props: SelectDialogProps) { @@ -29,7 +32,7 @@ export function SelectDialog(props: SelectDialogProps) { () => store.filter, async (filter) => { const needle = filter.toLowerCase() - const all = (typeof props.items === "function" ? await props.items(needle) : props.items) || [] + const all = (typeof props.items === "function" ? await props.items(needle).catch(() => []) : props.items) || [] const result = pipe( all, (x) => { @@ -64,6 +67,10 @@ export function SelectDialog(props: SelectDialogProps) { list.setActive(props.key(all[0])) } + onMount(() => { + resetSelection() + }) + createEffect(() => { store.filter scrollRef?.scrollTo(0, 0) @@ -88,7 +95,9 @@ export function SelectDialog(props: SelectDialogProps) { const handleSelect = (item: T) => { props.onSelect?.(item) - props.onClose?.() + if (!props.keepOpen) { + props.onClose?.() + } } const handleKey = (e: KeyboardEvent) => { @@ -100,7 +109,11 @@ export function SelectDialog(props: SelectDialogProps) { if (selected) handleSelect(selected) } else if (e.key === "Escape") { e.preventDefault() - props.onClose?.() + if (props.onBack) { + props.onBack() + } else { + props.onClose?.() + } } else { list.onKeyDown(e) } @@ -109,25 +122,47 @@ export function SelectDialog(props: SelectDialogProps) { return ( open || props.onClose?.()}> - +
- + + } + > + + + + handleInput(e.currentTarget.value)} onKeyDown={handleKey} placeholder={props.placeholder} - class="w-full pl-10 pr-4 py-2 rounded-t-md - text-sm text-text placeholder-text-muted/70 - focus:outline-none" + classList={{ + "w-full pr-4 py-2 rounded-t-xl text-sm text-text placeholder-text-muted/70 focus:outline-none": true, + "pl-10": !props.onBack, + "pl-9": !!props.onBack, + }} autofocus spellcheck={false} autocorrect="off" @@ -137,7 +172,7 @@ export function SelectDialog(props: SelectDialogProps) {
{/*
- +
*/} @@ -150,7 +185,7 @@ export function SelectDialog(props: SelectDialogProps) { resetSelection() }} > - +
@@ -181,7 +216,7 @@ export function SelectDialog(props: SelectDialogProps) { }} classList={{ "w-full px-3 py-2 flex items-center gap-3": true, - "rounded-md text-left transition-colors group": true, + "rounded-lg text-left transition-colors group": true, "bg-background-element": props.key(item) === list.active(), }} > diff --git a/packages/desktop/src/components/select.tsx b/packages/desktop/src/components/select.tsx index 6ab3f4012a..ceaa603fc1 100644 --- a/packages/desktop/src/components/select.tsx +++ b/packages/desktop/src/components/select.tsx @@ -57,7 +57,7 @@ export function Select(props: SelectProps & ButtonProps) { {props.label ? props.label(itemProps.item.rawValue) : (itemProps.item.rawValue as string)} - + )} diff --git a/packages/desktop/src/components/session-list.tsx b/packages/desktop/src/components/session-list.tsx index 5b6dc0f5a5..4260e3c9fd 100644 --- a/packages/desktop/src/components/session-list.tsx +++ b/packages/desktop/src/components/session-list.tsx @@ -1,38 +1,135 @@ import { useSync, useLocal } from "@/context" -import { Tooltip } from "@/ui" -import { DateTime } from "luxon" +import { Button } from "@/ui" import { VList } from "virtua/solid" +import { createMemo, createSignal } from "solid-js" +import { DateTime } from "luxon" + +type SessionOrHeader = { type: "header"; label: string; date: string } | { type: "session"; session: any } export default function SessionList() { const sync = useSync() const local = useLocal() + const [displayLimit, setDisplayLimit] = createSignal(50) + let listRef: any + + const flattenedList = createMemo(() => { + const sessions = sync.data.session + if (!sessions || sessions.length === 0) { + return [] + } + + console.log("[SessionList] Processing", sessions.length, "sessions") + + const items: SessionOrHeader[] = [] + let lastDate = "" + const limit = displayLimit() + + try { + const limitedSessions = sessions.slice(0, limit) + + limitedSessions.forEach((session, idx) => { + if (!session) { + console.warn("[SessionList] Null session at index", idx) + return + } + + if (!session.time?.created) { + items.push({ type: "session", session }) + return + } + + try { + const sessionDate = DateTime.fromMillis(session.time.created) + const dateKey = sessionDate.toFormat("yyyy-MM-dd") + + if (dateKey !== lastDate) { + const now = DateTime.now() + const today = now.toFormat("yyyy-MM-dd") + const yesterday = now.minus({ days: 1 }).toFormat("yyyy-MM-dd") + + let label = sessionDate.toFormat("MMMM d, yyyy") + if (dateKey === today) { + label = "Today" + } else if (dateKey === yesterday) { + label = "Yesterday" + } + + items.push({ type: "header", label, date: dateKey }) + lastDate = dateKey + } + + items.push({ type: "session", session }) + } catch (dateError) { + console.error("[SessionList] Error processing session date:", session.id, dateError) + items.push({ type: "session", session }) + } + }) + + console.log("[SessionList] Generated", items.length, "items from", limitedSessions.length, "sessions") + } catch (error) { + console.error("[SessionList] Error grouping sessions:", error) + return sessions.slice(0, limit).map((session) => ({ type: "session" as const, session })) + } + + return items + }) + + const items = flattenedList() + const hasMore = createMemo(() => sync.data.session.length > displayLimit()) + + console.log("[SessionList] Rendering", items.length, "items") + + const loadMore = () => { + setDisplayLimit((prev) => Math.min(prev + 50, sync.data.session.length)) + } + return ( - - {(session) => ( - - - - )} + {item.session.title || "Untitled"} + + ) + }} ) } diff --git a/packages/desktop/src/components/session-timeline.tsx b/packages/desktop/src/components/session-timeline.tsx index 07d93031e9..23ca026db6 100644 --- a/packages/desktop/src/components/session-timeline.tsx +++ b/packages/desktop/src/components/session-timeline.tsx @@ -1,4 +1,4 @@ -import { useLocal, useSync } from "@/context" +import { useSync } from "@/context" import { Collapsible, Icon } from "@/ui" import type { Part, ToolPart } from "@opencode-ai/sdk" import { DateTime } from "luxon" @@ -39,22 +39,28 @@ function Part(props: ParentProps & ComponentProps<"div">) { function CollapsiblePart(props: { title: ParentProps["children"] } & ParentProps & ComponentProps) { return ( - - - {props.title} - - -

- {props.children} -

-
-
+
+ +
+ +
+ + {props.title} +
+
+ +
+
{props.children}
+
+
+
+
+
) } function ReadToolPart(props: { part: ToolPart }) { const sync = useSync() - const local = useLocal() return ( @@ -64,9 +70,16 @@ function ReadToolPart(props: { part: ToolPart }) { {(state) => { const path = state().input["filePath"] as string return ( - local.file.open(path)}> - Read {getFilename(path)} - + + Read {getFilename(path)} + + } + > + + ) }} @@ -94,7 +107,7 @@ function EditToolPart(props: { part: ToolPart }) { {(state) => ( Edit {getFilename(state().input["filePath"] as string)} @@ -132,13 +145,14 @@ function WriteToolPart(props: { part: ToolPart }) { {(state) => ( Write {getFilename(state().input["filePath"] as string)} } > -
+
)}
@@ -166,14 +180,21 @@ function BashToolPart(props: { part: ToolPart }) { {(state) => ( - Run command: {state().input["command"]} + Bash } > - +
+
Command:
+ +
Output:
+
+                {state().output}
+              
+
)}
@@ -234,17 +255,37 @@ function ToolPart(props: { part: ToolPart }) { ) } -export default function SessionTimeline(props: { session: string; class?: string }) { +interface SessionTimelineProps { + session: string + class?: string + showDockZone?: boolean + onDockChat?: () => void +} + +export default function SessionTimeline(props: SessionTimelineProps) { const sync = useSync() const [scrollElement, setScrollElement] = createSignal(undefined) const [root, setRoot] = createSignal(undefined) const [tail, setTail] = createSignal(true) + const [loading, setLoading] = createSignal(false) + const [totalMessages, setTotalMessages] = createSignal(0) const size = createElementSize(root) const scroll = createScrollPosition(scrollElement) - onMount(() => sync.session.sync(props.session)) + onMount(async () => { + const result = await sync.session.sync(props.session, 20) + setTotalMessages(result?.total || 0) + console.log("[SessionTimeline] Loaded initial messages. Current:", messages().length, "Total:", result?.total) + }) const session = createMemo(() => sync.session.get(props.session)) const messages = createMemo(() => sync.data.message[props.session] ?? []) + const hasMore = createMemo(() => { + const total = totalMessages() + const current = messages().length + const more = total > 0 && current < total + console.log("[SessionTimeline] hasMore check - current:", current, "total:", total, "hasMore:", more) + return more + }) const working = createMemo(() => { const last = messages()[messages().length - 1] if (!last) return false @@ -286,13 +327,57 @@ export default function SessionTimeline(props: { session: string; class?: string }) let lastScrollY = 0 + let loadMoreTimeout: number | undefined createEffect(() => { - if (scroll.y < lastScrollY) { + const scrollY = scroll.y + if (scrollY < lastScrollY) { setTail(false) } - lastScrollY = scroll.y + + if (scrollY < 200 && !loading() && hasMore()) { + if (loadMoreTimeout) clearTimeout(loadMoreTimeout) + loadMoreTimeout = window.setTimeout(() => { + console.log( + "[SessionTimeline] Triggering load more - scrollY:", + scrollY, + "loading:", + loading(), + "hasMore:", + hasMore(), + ) + loadMoreMessages() + }, 300) + } + + lastScrollY = scrollY }) + const loadMoreMessages = async () => { + console.log("[SessionTimeline] Loading more messages...") + setLoading(true) + const element = scrollElement() + const previousScrollHeight = element?.scrollHeight || 0 + const previousScrollTop = element?.scrollTop || 0 + + try { + const result = await sync.session.loadMore(props.session, 20) + setTotalMessages(result.total) + console.log("[SessionTimeline] Loaded more messages. Now have:", result.loaded, "of", result.total) + + requestAnimationFrame(() => { + if (element) { + const newScrollHeight = element.scrollHeight + const heightDifference = newScrollHeight - previousScrollHeight + element.scrollTop = previousScrollTop + heightDifference + } + }) + } catch (error) { + console.error("[SessionTimeline] Error loading more messages:", error) + } finally { + setLoading(false) + } + } + const valid = (part: Part) => { if (!part) return false switch (part.type) { @@ -333,58 +418,78 @@ export default function SessionTimeline(props: { session: string; class?: string
-
    + +
    + Loading more messages... +
    +
    + +
    + Scroll up to load more messages ({messages().length} of {totalMessages()}) +
    +
    +
      - {(message) => ( - - {(part) => ( -
    • - {part.type}
}> - - {(part) => ( - - -
-

- {part().text} -

-

- {DateTime.fromMillis(message.time.created).toRelative()} ·{" "} - {sync.data.config.username ?? "user"} -

-
-
- - - -
- )} -
- - {(part) => ( - Thinking}> - - Thought for {duration(part())}s - -
- } - > - - - )} - - {(part) => } - - - )} - - )} + {(message) => { + const messageParts = createMemo(() => sync.data.part[message.id]?.filter(valid) ?? []) + return ( + + {(part) => ( +
  • + {part.type}
  • }> + + {(part) => ( + + +
    +

    + + {part().text} + +

    +

    + {DateTime.fromMillis(message.time.created).toRelative()} ·{" "} + {sync.data.config.username ?? "user"} +

    +
    +
    + + + +
    + )} +
    + + {(part) => ( + Thinking}> + + Thought for {duration(part())}s + + + } + > + + + )} + + {(part) => } + + + )} + + ) + }} diff --git a/packages/desktop/src/components/status-bar.tsx b/packages/desktop/src/components/status-bar.tsx new file mode 100644 index 0000000000..70bd623333 --- /dev/null +++ b/packages/desktop/src/components/status-bar.tsx @@ -0,0 +1,85 @@ +import { Icon, Tooltip } from "@/ui" +import { useSync } from "@/context" +import { Show, createSignal, createEffect } from "solid-js" + +export default function StatusBar() { + const sync = useSync() + const [notificationCount] = createSignal(0) + const [gitBranch, setGitBranch] = createSignal("") + + const version = "0.14.6" + + createEffect(async () => { + const dir = sync.data.path.directory + if (!dir) return + + if (typeof window !== "undefined" && "__TAURI__" in window) { + try { + const { invoke } = await import("@tauri-apps/api/core") + const branch = await invoke("get_git_branch", { path: dir }) + setGitBranch(branch) + } catch (err) { + setGitBranch("") + } + } + }) + + const handleFolderClick = async () => { + if (typeof window !== "undefined" && "__TAURI__" in window) { + try { + const { invoke } = await import("@tauri-apps/api/core") + const folderPath = await invoke("select_folder") + if (folderPath) { + await new Promise((resolve) => setTimeout(resolve, 500)) + await sync.load.path() + await sync.load.node() + window.location.reload() + } + } catch (err) { + console.error("Error selecting folder:", err) + } + } + } + + return ( +
    +
    + + + + + + +
    + + {gitBranch()} +
    +
    +
    +
    + +
    + +
    v{version}
    +
    + + + + +
    +
    + ) +} diff --git a/packages/desktop/src/components/suggestion-chips.tsx b/packages/desktop/src/components/suggestion-chips.tsx new file mode 100644 index 0000000000..7b62f14da9 --- /dev/null +++ b/packages/desktop/src/components/suggestion-chips.tsx @@ -0,0 +1,26 @@ +import { For } from "solid-js" + +interface SuggestionChipsProps { + suggestions: string[] + onSelect: (suggestion: string) => void + class?: string +} + +export default function SuggestionChips(props: SuggestionChipsProps) { + return ( +
    + + {(suggestion) => ( + + )} + +
    + ) +} diff --git a/packages/desktop/src/context/event.tsx b/packages/desktop/src/context/event.tsx index a2aa54181a..d0aaeb44b0 100644 --- a/packages/desktop/src/context/event.tsx +++ b/packages/desktop/src/context/event.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext, type ParentProps } from "solid-js" +import { createContext, useContext, onCleanup, type ParentProps } from "solid-js" import { createEventBus } from "@solid-primitives/event-bus" import type { Event as SDKEvent } from "@opencode-ai/sdk" import { useSDK } from "@/context" @@ -8,11 +8,23 @@ export type Event = SDKEvent // can extend with custom events later function init() { const sdk = useSDK() const bus = createEventBus() - sdk.event.subscribe().then(async (events) => { + let controller: AbortController | undefined + + const connect = async () => { + controller = new AbortController() + const events = await sdk.event.subscribe() for await (const event of events.stream) { + if (controller.signal.aborted) break bus.emit(event) } + } + + connect() + + onCleanup(() => { + controller?.abort() }) + return bus } diff --git a/packages/desktop/src/context/index.ts b/packages/desktop/src/context/index.ts index bc4bf3b1d9..6d0847f902 100644 --- a/packages/desktop/src/context/index.ts +++ b/packages/desktop/src/context/index.ts @@ -1,6 +1,7 @@ export { EventProvider, useEvent } from "./event" export { LocalProvider, useLocal } from "./local" export { MarkedProvider, useMarked } from "./marked" +export { MobileProvider, useMobile } from "./mobile" export { SDKProvider, useSDK } from "./sdk" export { ShikiProvider, useShiki } from "./shiki" export { SyncProvider, useSync } from "./sync" diff --git a/packages/desktop/src/context/local.tsx b/packages/desktop/src/context/local.tsx index e9fe8ee5cb..6e2d4e1695 100644 --- a/packages/desktop/src/context/local.tsx +++ b/packages/desktop/src/context/local.tsx @@ -185,16 +185,22 @@ function init() { const load = async (path: string) => { const relativePath = relative(path) - sdk.file.read({ query: { path: relativePath } }).then((x) => { - setStore( - "node", - relativePath, - produce((draft) => { - draft.loaded = true - draft.content = x.data - }), - ) - }) + sdk.file + .read({ query: { path: relativePath } }) + .then((x) => { + setStore( + "node", + relativePath, + produce((draft) => { + draft.loaded = true + draft.content = x.data + }), + ) + }) + .catch((err) => { + console.error("Failed to load file:", relativePath, err) + setStore("node", relativePath, "loaded", true) + }) } const fetch = async (path: string) => { @@ -233,17 +239,22 @@ function init() { } const list = async (path: string) => { - return sdk.file.list({ query: { path: path + "/" } }).then((x) => { - setStore( - "node", - produce((draft) => { - x.data!.forEach((node) => { - if (node.path in draft) return - draft[node.path] = node - }) - }), - ) - }) + return sdk.file + .list({ query: { path: path + "/" } }) + .then((x) => { + setStore( + "node", + produce((draft) => { + x.data?.forEach((node) => { + if (node.path in draft) return + draft[node.path] = node + }) + }), + ) + }) + .catch((err) => { + console.error("Failed to list files:", err) + }) } const search = (query: string) => sdk.find.files({ query: { query } }).then((x) => x.data!) @@ -463,7 +474,16 @@ function init() { const session = (() => { const [store, setStore] = createStore<{ active?: string - }>({}) + chatDocked: boolean + chatDockedPreference: boolean + }>({ + chatDocked: false, + chatDockedPreference: localStorage.getItem("chatDockedPreference") === "true", + }) + + createEffect(() => { + localStorage.setItem("chatDockedPreference", store.chatDockedPreference.toString()) + }) const active = createMemo(() => { if (!store.active) return undefined @@ -479,9 +499,26 @@ function init() { active, setActive(sessionId: string | undefined) { setStore("active", sessionId) + if (sessionId && store.chatDockedPreference) { + console.log("[session.setActive] Auto-docking chat based on preference") + setStore("chatDocked", true) + } }, clearActive() { + console.log("[session.clearActive] Clearing active session and undocking chat") setStore("active", undefined) + setStore("chatDocked", false) + }, + chatDocked: () => store.chatDocked, + dockChat() { + console.log("[session.dockChat] Docking chat and saving preference") + setStore("chatDocked", true) + setStore("chatDockedPreference", true) + }, + undockChat() { + console.log("[session.undockChat] Undocking chat and clearing preference") + setStore("chatDocked", false) + setStore("chatDockedPreference", false) }, } })() diff --git a/packages/desktop/src/context/mobile.tsx b/packages/desktop/src/context/mobile.tsx new file mode 100644 index 0000000000..3599d78fc3 --- /dev/null +++ b/packages/desktop/src/context/mobile.tsx @@ -0,0 +1,48 @@ +import { createContext, useContext, type ParentProps, createMemo } from "solid-js" +import { createMediaQuery, createViewportSize, isIOSDevice, isAndroidDevice, isTauri } from "@/utils/mobile" + +interface MobileContextValue { + isMobile: boolean + isIOS: boolean + isAndroid: boolean + isTauri: boolean + isPortrait: () => boolean + isLandscape: () => boolean + viewportSize: () => { width: number; height: number } +} + +const MobileContext = createContext() + +export function MobileProvider(props: ParentProps) { + const ios = isIOSDevice() + const android = isAndroidDevice() + const tauri = isTauri() + const isPortrait = createMediaQuery("(orientation: portrait)") + const isLandscape = createMediaQuery("(orientation: landscape)") + const viewportSize = createViewportSize() + const isMobileWidth = createMediaQuery("(max-width: 767px)") + + const mobile = createMemo(() => ios || android || isMobileWidth()) + + const value: MobileContextValue = { + get isMobile() { + return mobile() + }, + isIOS: ios, + isAndroid: android, + isTauri: tauri, + isPortrait, + isLandscape, + viewportSize, + } + + return {props.children} +} + +export function useMobile() { + const context = useContext(MobileContext) + if (!context) { + throw new Error("useMobile must be used within MobileProvider") + } + return context +} diff --git a/packages/desktop/src/context/sdk.tsx b/packages/desktop/src/context/sdk.tsx index f0d51ef57b..7863cdc808 100644 --- a/packages/desktop/src/context/sdk.tsx +++ b/packages/desktop/src/context/sdk.tsx @@ -1,30 +1,37 @@ import { createContext, useContext, type ParentProps } from "solid-js" -import { createOpencodeClient } from "@opencode-ai/sdk/client" - -const host = import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "127.0.0.1" -const port = import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096" - -function init() { - const client = createOpencodeClient({ - baseUrl: `http://${host}:${port}`, - fetch: (req) => { - return fetch({ - ...req, - // @ts-ignore - timeout: false, - }) - }, - }) - return client -} +import { createOpencodeClient, OpencodeClient, createClient } from "@opencode-ai/sdk/client" + +const host = import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost" +const defaultPort = import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096" -type SDKContext = ReturnType +type SDKContext = ReturnType const ctx = createContext() export function SDKProvider(props: ParentProps) { - const value = init() - return {props.children} + // Get directory from URL params or use desktop package directory as default + const directory = typeof window !== 'undefined' + ? new URLSearchParams(window.location.search).get('directory') || '/Users/jkneen/Documents/GitHub/flows/opencode-stt/packages/desktop' + : '/Users/jkneen/Documents/GitHub/flows/opencode-stt/packages/desktop' + + // Create the base client first - use empty baseUrl since Vite proxy handles it + const baseClient = createClient({ + baseUrl: "", + }) + + // Add request interceptor to inject directory query param + baseClient.interceptors.request.use((request) => { + const url = new URL(request.url) + url.searchParams.set('directory', directory) + const newUrl = url.toString() + console.log('[SDK Interceptor]', request.url, '->', newUrl) + return new Request(newUrl, request) + }) + + // Wrap in OpencodeClient + const client = new OpencodeClient({ client: baseClient }) + + return {props.children} } export function useSDK() { diff --git a/packages/desktop/src/context/sync.tsx b/packages/desktop/src/context/sync.tsx index 70883d8959..1de876f6bc 100644 --- a/packages/desktop/src/context/sync.tsx +++ b/packages/desktop/src/context/sync.tsx @@ -98,22 +98,60 @@ function init() { const sdk = useSDK() const load = { - provider: () => sdk.config.providers().then((x) => setStore("provider", x.data!.providers)), - path: () => sdk.path.get().then((x) => setStore("path", x.data!)), - agent: () => sdk.app.agents().then((x) => setStore("agent", x.data ?? [])), + provider: () => + sdk.config + .providers() + .then((x) => setStore("provider", x.data!.providers)) + .catch((e) => console.error('[Sync] Failed to load providers:', e)), + path: () => + sdk.path + .get() + .then((x) => setStore("path", x.data!)) + .catch((e) => console.error('[Sync] Failed to load path:', e)), + agent: () => + sdk.app + .agents() + .then((x) => setStore("agent", x.data ?? [])) + .catch((e) => console.error('[Sync] Failed to load agents:', e)), session: () => - sdk.session.list().then((x) => - setStore( - "session", - (x.data ?? []).slice().sort((a, b) => a.id.localeCompare(b.id)), - ), - ), - config: () => sdk.config.get().then((x) => setStore("config", x.data!)), - changes: () => sdk.file.status().then((x) => setStore("changes", x.data!)), - node: () => sdk.file.list({ query: { path: "/" } }).then((x) => setStore("node", x.data!)), + sdk.session + .list() + .then((x) => + setStore( + "session", + (x.data ?? []).slice().sort((a, b) => a.id.localeCompare(b.id)), + ), + ) + .catch((e) => console.error('[Sync] Failed to load sessions:', e)), + config: () => + sdk.config + .get() + .then((x) => setStore("config", x.data!)) + .catch((e) => console.error('[Sync] Failed to load config:', e)), + changes: () => + sdk.file + .status() + .then((x) => setStore("changes", x.data!)) + .catch((e) => console.error('[Sync] Failed to load changes:', e)), + node: () => + sdk.file + .list({ query: { path: "/" } }) + .then((x) => setStore("node", x.data!)) + .catch((e) => console.error('[Sync] Failed to load files:', e)), } - Promise.all(Object.values(load).map((p) => p())).then(() => setStore("ready", true)) + Promise.all(Object.values(load).map((p) => p())) + .then(() => { + console.log('[Sync] All data loaded:', { + providers: store.provider.length, + agents: store.agent.length, + sessions: store.session.length, + nodes: store.node.length, + path: store.path.directory, + }) + setStore("ready", true) + }) + .catch((e) => console.error('[Sync] Failed to load all data:', e)) const sanitizer = createMemo(() => new RegExp(`${store.path.directory}/`, "g")) const sanitize = (text: string) => text.replace(sanitizer(), "") @@ -128,24 +166,71 @@ function init() { if (match.found) return store.session[match.index] return undefined }, - async sync(sessionID: string) { + async sync(sessionID: string, limit?: number) { const [session, messages] = await Promise.all([ sdk.session.get({ path: { id: sessionID } }), sdk.session.messages({ path: { id: sessionID } }), ]) + const allMessages = messages.data! + const limitedMessages = limit ? allMessages.slice(-limit) : allMessages setStore( produce((draft) => { const match = Binary.search(draft.session, sessionID, (s) => s.id) draft.session[match.index] = session.data! - draft.message[sessionID] = messages - .data!.map((x) => x.info) + draft.message[sessionID] = limitedMessages + .map((x) => x.info) .slice() .sort((a, b) => a.id.localeCompare(b.id)) - for (const message of messages.data!) { + for (const message of limitedMessages) { draft.part[message.info.id] = message.parts.slice().sort((a, b) => a.id.localeCompare(b.id)) } }), ) + return { loaded: limitedMessages.length, total: allMessages.length } + }, + loadMoreCache: {} as { [sessionID: string]: any[] }, + async loadMore(sessionID: string, count: number = 10) { + console.log("[Sync] loadMore called for session:", sessionID, "count:", count) + + if (!this.loadMoreCache[sessionID]) { + console.log("[Sync] Fetching all messages for cache...") + const messages = await sdk.session.messages({ path: { id: sessionID } }) + this.loadMoreCache[sessionID] = messages.data! + } + + const allMessages = this.loadMoreCache[sessionID] + const currentMessages = store.message[sessionID] || [] + const currentCount = currentMessages.length + const newLimit = Math.min(currentCount + count, allMessages.length) + const messagesToLoad = allMessages.slice(-newLimit) + + console.log( + "[Sync] Loading", + messagesToLoad.length, + "messages (", + currentCount, + "->", + newLimit, + "of", + allMessages.length, + ")", + ) + + setStore( + produce((draft) => { + draft.message[sessionID] = messagesToLoad + .map((x: any) => x.info) + .slice() + .sort((a: any, b: any) => a.id.localeCompare(b.id)) + for (const message of messagesToLoad) { + if (!draft.part[message.info.id]) { + draft.part[message.info.id] = message.parts.slice().sort((a: any, b: any) => a.id.localeCompare(b.id)) + } + } + }), + ) + + return { loaded: messagesToLoad.length, total: allMessages.length } }, }, load, diff --git a/packages/desktop/src/context/theme.tsx b/packages/desktop/src/context/theme.tsx index 0b344ea978..7d6fe1bb5a 100644 --- a/packages/desktop/src/context/theme.tsx +++ b/packages/desktop/src/context/theme.tsx @@ -8,11 +8,26 @@ import { onCleanup, } from "solid-js" +export type FontSize = "smallest" | "small" | "default" | "large" | "largest" + +export interface FontSizes { + explorer: FontSize + editor: FontSize + timeline: FontSize + conversation: FontSize +} + export interface ThemeContextValue { theme: string | undefined isDark: boolean + fontSize: FontSize + fontSizes: FontSizes setTheme: (themeName: string) => void setDarkMode: (isDark: boolean) => void + setFontSize: (size: FontSize) => void + setAreaFontSize: (area: keyof FontSizes, size: FontSize) => void + previewTheme: (themeName: string, isDark: boolean) => void + clearPreview: () => void } const ThemeContext = createContext() @@ -30,11 +45,41 @@ interface ThemeProviderProps { defaultDarkMode?: boolean } -const themes = ["opencode", "tokyonight", "ayu", "nord", "catppuccin"] +export const themes = [ + "aura", + "ayu", + "catppuccin", + "cobalt2", + "dracula", + "everforest", + "github", + "gruvbox", + "kanagawa", + "material", + "matrix", + "monokai", + "nord", + "one-dark", + "opencode", + "palenight", + "rosepine", + "solarized", + "synthwave84", + "tokyonight", + "vesper", + "zenburn", +] export const ThemeProvider: ParentComponent = (props) => { const [theme, setThemeSignal] = createSignal() const [isDark, setIsDark] = createSignal(props.defaultDarkMode ?? false) + const [fontSize, setFontSizeSignal] = createSignal("default") + const [fontSizes, setFontSizes] = createSignal({ + explorer: "default", + editor: "default", + timeline: "default", + conversation: "default", + }) const handleKeyDown = (event: KeyboardEvent) => { if (event.key === "t" && event.ctrlKey) { @@ -58,16 +103,36 @@ export const ThemeProvider: ParentComponent = (props) => { onMount(() => { const savedTheme = localStorage.getItem("theme") ?? "opencode" const savedDarkMode = localStorage.getItem("darkMode") ?? "true" + const savedFontSize = (localStorage.getItem("fontSize") as FontSize) ?? "default" + const savedFontSizes = localStorage.getItem("fontSizes") + setIsDark(savedDarkMode === "true") + setFontSizeSignal(savedFontSize) + + if (savedFontSizes) { + try { + setFontSizes(JSON.parse(savedFontSizes)) + } catch (e) { + // ignore + } + } + setTheme(savedTheme) }) createEffect(() => { const currentTheme = theme() const darkMode = isDark() + const size = fontSize() + const sizes = fontSizes() if (currentTheme) { document.documentElement.setAttribute("data-theme", currentTheme) document.documentElement.setAttribute("data-dark", darkMode.toString()) + document.documentElement.setAttribute("data-font-size", size) + document.documentElement.setAttribute("data-font-explorer", sizes.explorer) + document.documentElement.setAttribute("data-font-editor", sizes.editor) + document.documentElement.setAttribute("data-font-timeline", sizes.timeline) + document.documentElement.setAttribute("data-font-conversation", sizes.conversation) } }) @@ -81,12 +146,57 @@ export const ThemeProvider: ParentComponent = (props) => { localStorage.setItem("darkMode", dark.toString()) } - const contextValue: ThemeContextValue = { - theme: theme(), - isDark: isDark(), - setTheme, - setDarkMode, + const setFontSize = (size: FontSize) => { + setFontSizeSignal(size) + localStorage.setItem("fontSize", size) + } + + const setAreaFontSize = (area: keyof FontSizes, size: FontSize) => { + setFontSizes((prev) => { + const updated = { ...prev, [area]: size } + localStorage.setItem("fontSizes", JSON.stringify(updated)) + return updated + }) + } + + const previewTheme = (themeName: string, isDark: boolean) => { + document.documentElement.setAttribute("data-theme", themeName) + document.documentElement.setAttribute("data-dark", isDark.toString()) + } + + const clearPreview = () => { + const currentTheme = theme() + const darkMode = isDark() + if (currentTheme) { + document.documentElement.setAttribute("data-theme", currentTheme) + document.documentElement.setAttribute("data-dark", darkMode.toString()) + } } - return {props.children} + return ( + + {props.children} + + ) } diff --git a/packages/desktop/src/index.css b/packages/desktop/src/index.css index cac2e91a65..89e1676c7f 100644 --- a/packages/desktop/src/index.css +++ b/packages/desktop/src/index.css @@ -2,6 +2,136 @@ :root { interpolate-size: allow-keywords; + + --safe-area-inset-top: env(safe-area-inset-top, 0px); + --safe-area-inset-right: env(safe-area-inset-right, 0px); + --safe-area-inset-bottom: env(safe-area-inset-bottom, 0px); + --safe-area-inset-left: env(safe-area-inset-left, 0px); +} + +[data-font-size="smallest"] .font-scalable { + font-size: 0.7rem !important; + line-height: 1.2 !important; +} + +[data-font-size="small"] .font-scalable { + font-size: 0.8rem !important; + line-height: 1.3 !important; +} + +[data-font-size="default"] .font-scalable { + font-size: 0.875rem !important; + line-height: 1.4 !important; +} + +[data-font-size="large"] .font-scalable { + font-size: 1rem !important; + line-height: 1.5 !important; +} + +[data-font-size="largest"] .font-scalable { + font-size: 1.25rem !important; + line-height: 1.6 !important; +} + +[data-font-explorer="smallest"] .font-explorer { + font-size: 0.7rem !important; + line-height: 1.2 !important; +} + +[data-font-explorer="small"] .font-explorer { + font-size: 0.8rem !important; + line-height: 1.3 !important; +} + +[data-font-explorer="default"] .font-explorer { + font-size: 0.875rem !important; + line-height: 1.4 !important; +} + +[data-font-explorer="large"] .font-explorer { + font-size: 1rem !important; + line-height: 1.5 !important; +} + +[data-font-explorer="largest"] .font-explorer { + font-size: 1.25rem !important; + line-height: 1.6 !important; +} + +[data-font-editor="smallest"] .font-editor { + font-size: 0.7rem !important; + line-height: 1.2 !important; +} + +[data-font-editor="small"] .font-editor { + font-size: 0.8rem !important; + line-height: 1.3 !important; +} + +[data-font-editor="default"] .font-editor { + font-size: 0.875rem !important; + line-height: 1.4 !important; +} + +[data-font-editor="large"] .font-editor { + font-size: 1rem !important; + line-height: 1.5 !important; +} + +[data-font-editor="largest"] .font-editor { + font-size: 1.25rem !important; + line-height: 1.6 !important; +} + +[data-font-timeline="smallest"] .font-timeline { + font-size: 0.7rem !important; + line-height: 1.2 !important; +} + +[data-font-timeline="small"] .font-timeline { + font-size: 0.8rem !important; + line-height: 1.3 !important; +} + +[data-font-timeline="default"] .font-timeline { + font-size: 0.875rem !important; + line-height: 1.4 !important; +} + +[data-font-timeline="large"] .font-timeline { + font-size: 1rem !important; + line-height: 1.5 !important; +} + +[data-font-timeline="largest"] .font-timeline { + font-size: 1.25rem !important; + line-height: 1.6 !important; +} + +[data-font-conversation="smallest"] .font-conversation { + font-size: 0.7rem !important; + line-height: 1.2 !important; +} + +[data-font-conversation="small"] .font-conversation { + font-size: 0.8rem !important; + line-height: 1.3 !important; +} + +[data-font-conversation="default"] .font-conversation { + font-size: 0.875rem !important; + line-height: 1.4 !important; +} + +[data-font-conversation="large"] .font-conversation { + font-size: 1rem !important; + line-height: 1.5 !important; +} + +[data-font-conversation="largest"] .font-conversation { + font-size: 1.25rem !important; + line-height: 1.6 !important; } @layer components { @@ -11,6 +141,86 @@ body { line-height: 1; + transform: translateZ(0); + } + + html, + body { + background-color: var(--color-background); + color-scheme: dark; + touch-action: pan-x pan-y; + -webkit-user-select: none; + user-select: none; + } + + input, + textarea { + -webkit-user-select: auto; + user-select: auto; + } + + /* GPU acceleration for timeline */ + [role="list"] { + contain: layout style paint; + content-visibility: auto; + transform: translateZ(0); + will-change: contents; + } + + [role="list"] > li { + contain: layout style paint; + content-visibility: auto; + transform: translateZ(0); + } + + /* GPU acceleration for all scrollable areas */ + [class*="overflow-y-auto"], + [class*="overflow-x-auto"], + [class*="overflow-auto"] { + transform: translateZ(0); + -webkit-overflow-scrolling: touch; + scroll-behavior: smooth; + } + + /* GPU acceleration for animated/interactive elements */ + button, + [role="button"], + a { + transform: translateZ(0); + } + + /* Optimize panel renders */ + [class*="bg-background"], + [class*="bg-background-panel"], + [class*="bg-background-element"] { + transform: translateZ(0); + } + + /* CSS containment for independent rendering contexts */ + [class*="border-r"], + [class*="border-l"] { + contain: layout style; + } + + /* Optimize file tree and list rendering */ + [role="tree"], + [role="listbox"] { + contain: layout style paint; + transform: translateZ(0); + } + + /* Optimize dialog/modal rendering */ + [role="dialog"], + [data-overlay] { + contain: layout style paint; + transform: translateZ(0); + will-change: opacity, transform; + } + + /* Optimize transitions and animations */ + [class*="transition"], + [class*="animate"] { + will-change: transform, opacity; } ::selection { @@ -32,6 +242,16 @@ scrollbar-color: var(--theme-border-subtle) var(--theme-background-panel); } + html { + scroll-behavior: smooth; + } + + @media (prefers-reduced-motion: no-preference) { + * { + scroll-snap-stop: normal; + } + } + .prose h1 { color: var(--color-text); font-size: var(--text-sm); @@ -100,6 +320,10 @@ .prose blockquote { margin-bottom: calc(var(--spacing) * 2); } + .prose { + max-width: none; + margin: 0; + } } @utility no-scrollbar { @@ -113,6 +337,18 @@ } } +@utility gpu-accelerate { + transform: translateZ(0); + backface-visibility: hidden; + perspective: 1000px; +} + +@utility gpu-smooth { + transform: translateZ(0); + will-change: transform; + backface-visibility: hidden; +} + @theme { --color-*: initial; --color-primary: var(--theme-primary); diff --git a/packages/desktop/src/index.tsx b/packages/desktop/src/index.tsx index 66ed93d3af..ac0f76a39e 100644 --- a/packages/desktop/src/index.tsx +++ b/packages/desktop/src/index.tsx @@ -12,6 +12,7 @@ import { ThemeProvider, ShikiProvider, MarkedProvider, + MobileProvider, } from "@/context" const root = document.getElementById("root") @@ -26,21 +27,23 @@ render( () => (
    - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + +
    ), diff --git a/packages/desktop/src/pages/index.tsx b/packages/desktop/src/pages/index.tsx index d520c86432..553777112b 100644 --- a/packages/desktop/src/pages/index.tsx +++ b/packages/desktop/src/pages/index.tsx @@ -1,30 +1,139 @@ -import { FileIcon, Icon, IconButton, Tooltip } from "@/ui" +import { FileIcon, Icon, IconButton, Tabs, Tooltip } from "@/ui" import * as KobalteTabs from "@kobalte/core/tabs" import FileTree from "@/components/file-tree" import EditorPane from "@/components/editor-pane" import { For, Match, onCleanup, onMount, Show, Switch } from "solid-js" import { SelectDialog } from "@/components/select-dialog" -import { useSync, useSDK, useLocal } from "@/context" -import type { LocalFile, TextSelection } from "@/context/local" +import { useLocal, useTheme, useSDK, useSync, useMobile } from "@/context" +import { themes, type FontSize } from "@/context/theme" +import { ResizeableLayout, ResizeablePane } from "@/components/resizeable-pane" +import type { LocalFile } from "@/context/local" import SessionList from "@/components/session-list" import SessionTimeline from "@/components/session-timeline" -import PromptForm, { type PromptContentPart, type PromptSubmitValue } from "@/components/prompt-form" +import PromptForm from "@/components/prompt-form" +import StatusBar from "@/components/status-bar" import { createStore } from "solid-js/store" import { getDirectory, getFilename } from "@/utils" -import { Select } from "@/components/select" -import { Tabs } from "@/ui/tabs" -import { Code } from "@/components/code" +import MobileLayout from "@/components/mobile-layout" export default function Page() { const local = useLocal() - const sync = useSync() + const theme = useTheme() const sdk = useSDK() + const sync = useSync() + const mobile = useMobile() + const [store, setStore] = createStore({ clickTimer: undefined as number | undefined, modelSelectOpen: false, + agentSelectOpen: false, fileSelectOpen: false, + commandPaletteOpen: false, + commandPaletteView: "main" as "main" | "theme" | "fontSize" | "fontSizeArea", + fontSizeArea: undefined as "explorer" | "editor" | "timeline" | "conversation" | undefined, + dragProximity: { isDragging: false, nearDockZone: false, x: 0, y: 0 }, }) + const hasWorkspace = () => { + const dir = sync.data.path.directory + const nodeCount = sync.data.node.length + + console.log("=== hasWorkspace CHECK ===") + console.log("Directory:", dir) + console.log("Node count:", nodeCount) + console.log("Query params:", window.location.search) + + if (!dir || dir.length === 0) { + console.log("REJECTED: No directory") + return false + } + + if (dir === "/" || dir === "~" || dir === ".") { + console.log("REJECTED: Root/home/current directory") + return false + } + + if ( + dir.startsWith("/System") || + dir.startsWith("/usr") || + dir.startsWith("/bin") || + dir.startsWith("/sbin") || + dir.startsWith("/private") + ) { + console.log("REJECTED: System directory") + return false + } + + if (sync.data.node.length === 0) { + console.log("REJECTED: No files loaded") + return false + } + + if (!dir.startsWith("/Users/") && !dir.startsWith("/home/")) { + console.log("REJECTED: Not in user directory") + return false + } + + console.log("ACCEPTED: Valid workspace") + return true + } + + const handleOpenFolder = async () => { + if (typeof window !== "undefined" && "__TAURI__" in window) { + try { + const { invoke } = await import("@tauri-apps/api/core") + const folderPath = await invoke("select_folder") + if (folderPath) { + await new Promise((resolve) => setTimeout(resolve, 500)) + await sync.load.path() + await sync.load.node() + window.location.reload() + } + } catch (err) { + console.error("Error selecting folder:", err) + } + } + } + + const handleFolderDrop = async (e: DragEvent) => { + e.preventDefault() + e.stopPropagation() + + if (typeof window !== "undefined" && "__TAURI__" in window) { + const files = e.dataTransfer?.files + + if (files && files.length > 0) { + for (let i = 0; i < files.length; i++) { + const file = files[i] as any + + if (file.path) { + try { + const { invoke } = await import("@tauri-apps/api/core") + await invoke("select_folder") + await new Promise((resolve) => setTimeout(resolve, 500)) + await sync.load.path() + await sync.load.node() + window.location.reload() + } catch (err) { + console.error("Error loading folder:", err) + } + return + } + } + } + } + } + + const handleDragOver = (e: DragEvent) => { + e.preventDefault() + e.stopPropagation() + } + + let previewTimer: number | undefined + + const layoutKey = "workspace" + const timelinePane = "timeline" + let inputRef: HTMLTextAreaElement | undefined = undefined const MOD = typeof navigator === "object" && /(Mac|iPod|iPhone|iPad)/.test(navigator.platform) ? "Meta" : "Control" @@ -38,9 +147,16 @@ export default function Page() { }) const handleKeyDown = (event: KeyboardEvent) => { + if (event.getModifierState(MOD) && event.key === ",") { + event.preventDefault() + setStore("commandPaletteOpen", true) + setStore("commandPaletteView", "main") + return + } if (event.getModifierState(MOD) && event.shiftKey && event.key.toLowerCase() === "p") { event.preventDefault() - // TODO: command palette + setStore("commandPaletteOpen", true) + setStore("commandPaletteView", "main") return } if (event.getModifierState(MOD) && event.key.toLowerCase() === "p") { @@ -106,8 +222,24 @@ export default function Page() { } } - const handlePromptSubmit = async (prompt: PromptSubmitValue) => { - const existingSession = local.session.active() + const handleDragProximity = (proximity: { isDragging: boolean; nearDockZone: boolean; x: number; y: number }) => { + setStore("dragProximity", proximity) + } + + const handleDrop = () => { + console.log("[handleDrop] Called! Timeline visible:", local.layout.visible(layoutKey, timelinePane)) + if (local.layout.visible(layoutKey, timelinePane)) { + console.log("[handleDrop] Docking chat now!") + local.session.dockChat() + } + } + + const handleDockChat = () => { + local.session.dockChat() + } + + const handlePromptSubmit = async (prompt: string) => { + const existingSession = local.layout.visible(layoutKey, timelinePane) ? local.session.active() : undefined let session = existingSession if (!session) { const created = await sdk.session.create() @@ -115,84 +247,7 @@ export default function Page() { } if (!session) return local.session.setActive(session.id) - - interface SubmissionAttachment { - path: string - selection?: TextSelection - label: string - } - - const createAttachmentKey = (path: string, selection?: TextSelection) => { - if (!selection) return path - return `${path}:${selection.startLine}:${selection.startChar}:${selection.endLine}:${selection.endChar}` - } - - const formatAttachmentLabel = (path: string, selection?: TextSelection) => { - if (!selection) return getFilename(path) - return `${getFilename(path)} (${selection.startLine}-${selection.endLine})` - } - - const toAbsolutePath = (path: string) => (path.startsWith("/") ? path : sync.absolute(path)) - - const attachments = new Map() - - const registerAttachment = (path: string, selection: TextSelection | undefined, label?: string) => { - if (!path) return - const key = createAttachmentKey(path, selection) - if (attachments.has(key)) return - attachments.set(key, { - path, - selection, - label: label ?? formatAttachmentLabel(path, selection), - }) - } - - const promptAttachments = prompt.parts.filter( - (part): part is Extract => part.kind === "attachment", - ) - - for (const part of promptAttachments) { - registerAttachment(part.path, part.selection, part.display) - } - - const activeFile = local.context.active() - if (activeFile) { - registerAttachment( - activeFile.path, - activeFile.selection, - activeFile.name ?? formatAttachmentLabel(activeFile.path, activeFile.selection), - ) - } - - for (const contextFile of local.context.all()) { - registerAttachment( - contextFile.path, - contextFile.selection, - formatAttachmentLabel(contextFile.path, contextFile.selection), - ) - } - - const attachmentParts = Array.from(attachments.values()).map((attachment) => { - const absolute = toAbsolutePath(attachment.path) - const query = attachment.selection - ? `?start=${attachment.selection.startLine}&end=${attachment.selection.endLine}` - : "" - return { - type: "file" as const, - mime: "text/plain", - url: `file://${absolute}${query}`, - filename: getFilename(attachment.path), - source: { - type: "file" as const, - text: { - value: `@${attachment.label}`, - start: 0, - end: 0, - }, - path: absolute, - }, - } - }) + local.layout.show(layoutKey, timelinePane) await sdk.session.prompt({ path: { id: session.id }, @@ -205,148 +260,556 @@ export default function Page() { parts: [ { type: "text", - text: prompt.text, + text: prompt, }, - ...attachmentParts, + ...(local.context.active() + ? [ + { + type: "file" as const, + mime: "text/plain", + url: `file://${local.context.active()!.absolute}`, + filename: local.context.active()!.name, + source: { + type: "file" as const, + text: { + value: "@" + local.context.active()!.name, + start: 0, + end: 0, + }, + path: local.context.active()!.absolute, + }, + }, + ] + : []), + ...local.context.all().flatMap((file) => [ + { + type: "file" as const, + mime: "text/plain", + url: `file://${sync.absolute(file.path)}${file.selection ? `?start=${file.selection.startLine}&end=${file.selection.endLine}` : ""}`, + filename: getFilename(file.path), + source: { + type: "file" as const, + text: { + value: "@" + getFilename(file.path), + start: 0, + end: 0, + }, + path: sync.absolute(file.path), + }, + }, + ]), ], }, }) } - const plus = ( - setStore("fileSelectOpen", true)} - > - - - ) - return ( -
    -
    -
    - -
    - - {(activeSession) => } - -
    - - } + } + > + setStore("modelSelectOpen", true)} + onOpenAgentSelect={() => setStore("agentSelectOpen", true)} + /> + } + > +
    + -
      - - {(path) => ( -
    • - -
    • + + +
      + + + Files + + + Changes + + +
      + + { + setStore("commandPaletteOpen", true) + setStore("commandPaletteView", "main") + }} + size="xs" + variant="ghost" + > + + + +
      +
      + + + + + No changes
    } + > +
      + + {(path) => ( +
    • + +
    • + )} +
      +
    +
    + + + + + setStore("modelSelectOpen", true)} + onOpenAgentSelect={() => setStore("agentSelectOpen", true)} + onInputRefChange={(element: HTMLTextAreaElement | null) => { + inputRef = element ?? undefined + }} + onPromptSubmit={handlePromptSubmit} + onDragProximity={handleDragProximity} + onDrop={handleDrop} + hideFloatingChat={local.session.chatDocked()} + /> + + + }> + {(activeSession) => ( +
    +
    +
    + { + local.session.clearActive() + }} + class="text-text-muted hover:text-text" + > + + +

    + {activeSession().title || "Untitled Session"} +

    + + local.session.undockChat()} + class="text-text-muted hover:text-text ml-auto" + title="Undock chat" + > + + + +
    +
    +
    + +
    + +
    +
    { + console.log("[Drag handle] Mouse down") + e.preventDefault() + const startY = e.clientY + let hasMoved = false + + const handleMove = (moveEvent: MouseEvent) => { + const deltaY = startY - moveEvent.clientY + console.log("[Drag handle] Delta Y:", deltaY) + if (Math.abs(deltaY) > 10) { + hasMoved = true + } + if (hasMoved && deltaY > 30) { + console.log("[Drag handle] Undocking chat - dragged up") + local.session.undockChat() + document.removeEventListener("mousemove", handleMove) + document.removeEventListener("mouseup", handleUp) + } + } + + const handleUp = () => { + console.log("[Drag handle] Mouse up") + document.removeEventListener("mousemove", handleMove) + document.removeEventListener("mouseup", handleUp) + } + + document.addEventListener("mousemove", handleMove) + document.addEventListener("mouseup", handleUp) + }} + > +
    +
    +
    + setStore("modelSelectOpen", true)} + onOpenAgentSelect={() => setStore("agentSelectOpen", true)} + docked={true} + /> +
    +
    + + +
    +
    + + Drop to dock chat here + +
    +
    +
    +
    )} - - +
    + + + + x} + render={(i) => ( +
    +
    + + {getFilename(i)} + + {getDirectory(i)} + +
    +
    +
    + )} + onClose={() => setStore("fileSelectOpen", false)} + onSelect={(x) => (x ? local.file.open(x, { pinned: true }) : undefined)} + />
    + + + + items={[ + { id: "theme", name: "Preferences: Color Theme", description: "Change color theme", action: "theme" }, + { id: "fontSize", name: "Preferences: Font Size", description: "Change font size", action: "fontSize" }, + ]} + key={(x) => x.id} + placeholder="Type a command..." + keepOpen={true} + render={(i) => ( +
    +
    {i.name}
    +
    {i.description}
    +
    + )} + filter={["name", "description"]} + onClose={() => { + setStore("commandPaletteOpen", false) + }} + onSelect={(item) => { + if (item?.action === "theme") { + setStore("commandPaletteView", "theme") + } else if (item?.action === "fontSize") { + setStore("commandPaletteView", "fontSize") + } + }} + /> +
    + + + + items={[ + ...themes.map((t) => ({ + id: `theme-${t}-light`, + name: t.charAt(0).toUpperCase() + t.slice(1).replace(/-/g, " "), + value: "Light", + themeName: t, + isDark: false, + })), + ...themes.map((t) => ({ + id: `theme-${t}-dark`, + name: t.charAt(0).toUpperCase() + t.slice(1).replace(/-/g, " "), + value: "Dark", + themeName: t, + isDark: true, + })), + ]} + key={(x) => x.id} + placeholder="Select theme..." + reduceBlur={true} + groupBy={(x) => x.value} + onBack={() => { + theme.clearPreview() + setStore("commandPaletteView", "main") + }} + render={(i) => { + const isActive = i.themeName === theme.theme && i.isDark === theme.isDark + return ( +
    { + if (previewTimer) clearTimeout(previewTimer) + theme.previewTheme(i.themeName, i.isDark) + }} + onMouseLeave={() => { + if (previewTimer) clearTimeout(previewTimer) + previewTimer = window.setTimeout(() => theme.clearPreview(), 100) + }} + > +
    + {i.name} + {isActive && } +
    +
    + ) + }} + filter={["name"]} + onClose={() => { + theme.clearPreview() + setStore("commandPaletteOpen", false) + }} + onSelect={(item) => { + if (item) { + theme.setTheme(item.themeName) + theme.setDarkMode(item.isDark) + } + setStore("commandPaletteOpen", false) + }} + /> +
    + + + + items={[ + { + id: "area-explorer", + name: "File Explorer", + description: "File & folder list", + area: "explorer" as const, + }, + { id: "area-editor", name: "Editor", description: "Code editor pane", area: "editor" as const }, + { id: "area-timeline", name: "Timeline", description: "Session timeline", area: "timeline" as const }, + { + id: "area-conversation", + name: "Conversation", + description: "Chat messages", + area: "conversation" as const, + }, + ]} + key={(x) => x.id} + placeholder="Select area..." + onBack={() => setStore("commandPaletteView", "main")} + keepOpen={true} + render={(i) => ( +
    +
    {i.name}
    +
    {i.description}
    +
    + )} + filter={["name", "description"]} + onClose={() => setStore("commandPaletteOpen", false)} + onSelect={(item) => { + if (item) { + setStore("fontSizeArea", item.area) + setStore("commandPaletteView", "fontSizeArea") + } + }} + /> +
    + + + + items={[ + { id: "font-smallest", name: "Smallest", fontSize: "smallest" }, + { id: "font-small", name: "Small", fontSize: "small" }, + { id: "font-default", name: "Default", fontSize: "default" }, + { id: "font-large", name: "Large", fontSize: "large" }, + { id: "font-largest", name: "Largest", fontSize: "largest" }, + ]} + key={(x) => x.id} + placeholder="Select font size..." + onBack={() => setStore("commandPaletteView", "fontSize")} + render={(i) => { + const isActive = store.fontSizeArea && i.fontSize === theme.fontSizes[store.fontSizeArea] + return ( +
    +
    + {i.name} + {isActive && } +
    +
    + ) + }} + filter={["name"]} + onClose={() => setStore("commandPaletteOpen", false)} + onSelect={(item) => { + if (item && store.fontSizeArea) { + theme.setAreaFontSize(store.fontSizeArea, item.fontSize) + } + setStore("commandPaletteOpen", false) + }} + /> +
    +
    - -
    - setStore("modelSelectOpen", true)} - onInputRefChange={(element: HTMLTextAreaElement | undefined) => { - inputRef = element ?? undefined - }} - /> -
    -
    - - `${x.provider.id}:${x.id}`} - items={local.model.list()} - current={local.model.current()} - render={(i) => ( -
    -
    - - {i.name} - - {i.id} - -
    -
    - - - - - - - - - -
    - {new Intl.NumberFormat("en-US", { - notation: "compact", - compactDisplay: "short", - }).format(i.limit.context)} + + `${x.provider.id}:${x.id}`} + items={local.model.list()} + current={local.model.current()} + render={(i) => ( +
    +
    + + {i.name} + + {i.id} +
    - -
    - - 10}>$$$ - 1}>$$ - 0.1}>$ - +
    + + + + + + + + + +
    + {new Intl.NumberFormat("en-US", { + notation: "compact", + compactDisplay: "short", + }).format(i.limit.context)}
    - + +
    + + 10}>$$$ + 1}>$$ + 0.1}>$ + +
    +
    +
    -
    - )} - filter={["provider.name", "name", "id"]} - groupBy={(x) => x.provider.name} - onClose={() => setStore("modelSelectOpen", false)} - onSelect={(x) => local.model.set(x ? { modelID: x.id, providerID: x.provider.id } : undefined)} - /> -
    - - x} - render={(i) => ( -
    -
    - - {getFilename(i)} - - {getDirectory(i)} - + )} + filter={["provider.name", "name", "id"]} + groupBy={(x) => x.provider.name} + onClose={() => setStore("modelSelectOpen", false)} + onSelect={(x) => local.model.set(x ? { modelID: x.id, providerID: x.provider.id } : undefined)} + /> + + + x.name} + items={local.agent.list()} + current={local.agent.current()} + render={(i) => ( +
    +
    + + {i.name} +
    -
    -
    - )} - onClose={() => setStore("fileSelectOpen", false)} - onSelect={(x) => (x ? local.context.openFile(x) : undefined)} - // onSelect={(x) => (x ? local.file.open(x, { pinned: true }) : undefined)} - /> + )} + filter={["name"]} + placeholder="Select agent..." + onClose={() => setStore("agentSelectOpen", false)} + onSelect={(x) => x && local.agent.set(x.name)} + /> + -
    +
    ) } diff --git a/packages/desktop/src/ui/index.ts b/packages/desktop/src/ui/index.ts index d3f24a192b..c54834f33f 100644 --- a/packages/desktop/src/ui/index.ts +++ b/packages/desktop/src/ui/index.ts @@ -10,4 +10,11 @@ export { Icon, type IconProps } from "./icon" export { IconButton, type IconButtonProps } from "./icon-button" export { Link, type LinkProps } from "./link" export { Logo, type LogoProps } from "./logo" +export { + Tabs, + type TabsProps, + type TabsListProps, + type TabsTriggerProps, + type TabsContentProps, +} from "./tabs" export { Tooltip, type TooltipProps } from "./tooltip" diff --git a/packages/desktop/src/utils/index.ts b/packages/desktop/src/utils/index.ts index ae89e44174..f74bcb7695 100644 --- a/packages/desktop/src/utils/index.ts +++ b/packages/desktop/src/utils/index.ts @@ -1,2 +1,3 @@ export * from "./path" export * from "./dom" +export * from "./mobile" diff --git a/packages/desktop/src/utils/mobile.ts b/packages/desktop/src/utils/mobile.ts new file mode 100644 index 0000000000..c6dd4460f3 --- /dev/null +++ b/packages/desktop/src/utils/mobile.ts @@ -0,0 +1,155 @@ +import { createSignal, createEffect, onCleanup } from "solid-js" + +export const isMobile = () => { + if (typeof window === "undefined") return false + return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) || window.innerWidth < 768 +} + +export const isIOSDevice = () => { + if (typeof window === "undefined") return false + return /iPhone|iPad|iPod/i.test(navigator.userAgent) +} + +export const isIOS = () => { + if (typeof window === "undefined") return false + return /iPhone|iPad|iPod/i.test(navigator.userAgent) +} + +export const isAndroidDevice = () => { + if (typeof window === "undefined") return false + return /Android/i.test(navigator.userAgent) +} + +export const isAndroid = () => { + if (typeof window === "undefined") return false + return /Android/i.test(navigator.userAgent) +} + +export const isTauri = () => { + return typeof window !== "undefined" && "__TAURI__" in window +} + +export const createMediaQuery = (query: string) => { + const [matches, setMatches] = createSignal(false) + + createEffect(() => { + if (typeof window === "undefined") return + + const mediaQuery = window.matchMedia(query) + setMatches(mediaQuery.matches) + + const handler = (event: MediaQueryListEvent) => setMatches(event.matches) + mediaQuery.addEventListener("change", handler) + + onCleanup(() => mediaQuery.removeEventListener("change", handler)) + }) + + return matches +} + +export const createViewportSize = () => { + const [size, setSize] = createSignal({ + width: typeof window !== "undefined" ? window.innerWidth : 0, + height: typeof window !== "undefined" ? window.innerHeight : 0, + }) + + createEffect(() => { + if (typeof window === "undefined") return + + const handleResize = () => { + setSize({ + width: window.innerWidth, + height: window.innerHeight, + }) + } + + window.addEventListener("resize", handleResize) + onCleanup(() => window.removeEventListener("resize", handleResize)) + }) + + return size +} + +export const getSafeAreaInsets = () => { + if (typeof window === "undefined" || typeof getComputedStyle === "undefined") { + return { top: 0, right: 0, bottom: 0, left: 0 } + } + + const style = getComputedStyle(document.documentElement) + + return { + top: parseInt(style.getPropertyValue("--safe-area-inset-top") || "0"), + right: parseInt(style.getPropertyValue("--safe-area-inset-right") || "0"), + bottom: parseInt(style.getPropertyValue("--safe-area-inset-bottom") || "0"), + left: parseInt(style.getPropertyValue("--safe-area-inset-left") || "0"), + } +} + +export const MOBILE_BREAKPOINT = 768 +export const TABLET_BREAKPOINT = 1024 + +export type SwipeDirection = "up" | "down" | "left" | "right" + +export interface SwipeHandlers { + onSwipeLeft?: () => void + onSwipeRight?: () => void + onSwipeUp?: () => void + onSwipeDown?: () => void +} + +export const createSwipeGesture = (element: HTMLElement, handlers: SwipeHandlers) => { + let touchStartX = 0 + let touchStartY = 0 + let touchEndX = 0 + let touchEndY = 0 + + const minSwipeDistance = 50 + + const handleTouchStart = (e: TouchEvent) => { + touchStartX = e.changedTouches[0].screenX + touchStartY = e.changedTouches[0].screenY + } + + const handleTouchEnd = (e: TouchEvent) => { + touchEndX = e.changedTouches[0].screenX + touchEndY = e.changedTouches[0].screenY + handleGesture() + } + + const handleGesture = () => { + const diffX = touchEndX - touchStartX + const diffY = touchEndY - touchStartY + + if (Math.abs(diffX) > Math.abs(diffY)) { + if (Math.abs(diffX) > minSwipeDistance) { + if (diffX > 0) { + handlers.onSwipeRight?.() + } else { + handlers.onSwipeLeft?.() + } + } + } else { + if (Math.abs(diffY) > minSwipeDistance) { + if (diffY > 0) { + handlers.onSwipeDown?.() + } else { + handlers.onSwipeUp?.() + } + } + } + } + + element.addEventListener("touchstart", handleTouchStart) + element.addEventListener("touchend", handleTouchEnd) + + return () => { + element.removeEventListener("touchstart", handleTouchStart) + element.removeEventListener("touchend", handleTouchEnd) + } +} + +export const vibrate = (pattern: number | number[] = 10) => { + if (typeof window !== "undefined" && "vibrate" in navigator) { + navigator.vibrate(pattern) + } +} diff --git a/packages/desktop/src/utils/speech.ts b/packages/desktop/src/utils/speech.ts index 921e0a159b..d9f6d8754c 100644 --- a/packages/desktop/src/utils/speech.ts +++ b/packages/desktop/src/utils/speech.ts @@ -250,8 +250,17 @@ export function createSpeechRecognition(opts?: { } } - const start = () => { + const start = async () => { if (!recognition) return + + // Request microphone permission explicitly + try { + await navigator.mediaDevices.getUserMedia({ audio: true }) + } catch (err) { + console.error("Microphone permission denied:", err) + return + } + shouldContinue = true sessionCommitted = "" pendingHypothesis = "" diff --git a/packages/desktop/tsconfig.json b/packages/desktop/tsconfig.json index 82541a6d3e..9c1df76b08 100644 --- a/packages/desktop/tsconfig.json +++ b/packages/desktop/tsconfig.json @@ -16,5 +16,6 @@ "paths": { "@/*": ["./src/*"] } - } + }, + "exclude": ["src-tauri/target", "node_modules"] } diff --git a/packages/desktop/vite.config.ts b/packages/desktop/vite.config.ts index e0a62f5f56..96506d94cd 100644 --- a/packages/desktop/vite.config.ts +++ b/packages/desktop/vite.config.ts @@ -10,6 +10,11 @@ export default defineConfig({ alias: { "@": path.resolve(__dirname, "./src"), }, + conditions: ["solid"], + }, + esbuild: { + jsx: "automatic", + jsxImportSource: "solid-js", }, plugins: [ generateThemeCSS(), @@ -23,8 +28,17 @@ export default defineConfig({ }), ], server: { - host: "0.0.0.0", - port: 3000, + host: process.env["TAURI_DEV_HOST"] || "127.0.0.1", + port: parseInt(process.env["PORT"] || "5173"), + strictPort: false, + proxy: { + '/session': 'http://127.0.0.1:4096', + '/config': 'http://127.0.0.1:4096', + '/agent': 'http://127.0.0.1:4096', + '/file': 'http://127.0.0.1:4096', + '/path': 'http://127.0.0.1:4096', + '/event': 'http://127.0.0.1:4096', + }, }, build: { target: "esnext", diff --git a/packages/opencode/src/cli/cmd/tui/thread.ts b/packages/opencode/src/cli/cmd/tui/thread.ts index dde93bdc5d..be07189bd0 100644 --- a/packages/opencode/src/cli/cmd/tui/thread.ts +++ b/packages/opencode/src/cli/cmd/tui/thread.ts @@ -26,7 +26,7 @@ export const TuiThreadCommand = cmd({ }), handler: async (args) => { upgrade() - const worker = new Worker("./src/cli/cmd/tui/worker.ts") + const worker = new Worker(new URL("./worker.ts", import.meta.url)) worker.onerror = console.error const client = Rpc.client(worker) process.on("uncaughtException", (e) => { diff --git a/packages/sdk/js/src/client.ts b/packages/sdk/js/src/client.ts index 29b9de9062..fd40fdcebc 100644 --- a/packages/sdk/js/src/client.ts +++ b/packages/sdk/js/src/client.ts @@ -5,6 +5,8 @@ import { createClient } from "./gen/client/client.gen.js" import { type Config } from "./gen/client/types.gen.js" import { OpencodeClient } from "./gen/sdk.gen.js" +export { createClient } + export function createOpencodeClient(config?: Config) { const client = createClient(config) return new OpencodeClient({ client })