diff --git a/.github/workflows/docs-locale-sync.yml b/.github/workflows/docs-locale-sync.yml index 2bc19d6141..fff2ec4292 100644 --- a/.github/workflows/docs-locale-sync.yml +++ b/.github/workflows/docs-locale-sync.yml @@ -59,43 +59,10 @@ jobs: { "permission": { "*": "deny", - "read": { - "*": "deny", - "packages/web/src/content/docs": "allow", - "packages/web/src/content/docs/*": "allow", - "packages/web/src/content/docs/*.mdx": "allow", - "packages/web/src/content/docs/*/*.mdx": "allow", - ".opencode": "allow", - ".opencode/agent": "allow", - ".opencode/glossary": "allow", - ".opencode/agent/translator.md": "allow", - ".opencode/glossary/*.md": "allow" - }, - "edit": { - "*": "deny", - "packages/web/src/content/docs/*/*.mdx": "allow" - }, - "glob": { - "*": "deny", - "packages/web/src/content/docs*": "allow", - ".opencode/glossary*": "allow" - }, - "task": { - "*": "deny", - "translator": "allow" - } - }, - "agent": { - "translator": { - "permission": { - "*": "deny", - "read": { - "*": "deny", - ".opencode/agent/translator.md": "allow", - ".opencode/glossary/*.md": "allow" - } - } - } + "read": "allow", + "edit": "allow", + "glob": "allow", + "task": "allow" } } run: | diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8d4c9038a7..f3227d0927 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -99,7 +99,6 @@ jobs: with: name: opencode-cli path: packages/opencode/dist - outputs: version: ${{ needs.version.outputs.version }} @@ -240,11 +239,130 @@ jobs: APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }} APPLE_API_KEY_PATH: ${{ runner.temp }}/apple-api-key.p8 + build-electron: + needs: + - build-cli + - version + continue-on-error: false + strategy: + fail-fast: false + matrix: + settings: + - host: macos-latest + target: x86_64-apple-darwin + platform_flag: --mac --x64 + - host: macos-latest + target: aarch64-apple-darwin + platform_flag: --mac --arm64 + - host: "blacksmith-4vcpu-windows-2025" + target: x86_64-pc-windows-msvc + platform_flag: --win + - host: "blacksmith-4vcpu-ubuntu-2404" + target: x86_64-unknown-linux-gnu + platform_flag: --linux + - host: "blacksmith-4vcpu-ubuntu-2404" + target: aarch64-unknown-linux-gnu + platform_flag: --linux + runs-on: ${{ matrix.settings.host }} + steps: + - uses: actions/checkout@v3 + + - uses: apple-actions/import-codesign-certs@v2 + if: runner.os == 'macOS' + with: + keychain: build + p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }} + p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + + - name: Setup Apple API Key + if: runner.os == 'macOS' + run: echo "${{ secrets.APPLE_API_KEY_PATH }}" > $RUNNER_TEMP/apple-api-key.p8 + + - uses: ./.github/actions/setup-bun + + - uses: actions/setup-node@v4 + with: + node-version: "24" + + - name: Cache apt packages + if: contains(matrix.settings.host, 'ubuntu') + uses: actions/cache@v4 + with: + path: ~/apt-cache + key: ${{ runner.os }}-${{ matrix.settings.target }}-apt-electron-${{ hashFiles('.github/workflows/publish.yml') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.settings.target }}-apt-electron- + + - name: Install dependencies (ubuntu only) + if: contains(matrix.settings.host, 'ubuntu') + run: | + mkdir -p ~/apt-cache && chmod -R a+rw ~/apt-cache + sudo apt-get update + sudo apt-get install -y --no-install-recommends -o dir::cache::archives="$HOME/apt-cache" rpm + sudo chmod -R a+rw ~/apt-cache + + - name: Setup git committer + id: committer + uses: ./.github/actions/setup-git-committer + with: + opencode-app-id: ${{ vars.OPENCODE_APP_ID }} + opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} + + - name: Prepare + run: bun ./scripts/prepare.ts + working-directory: packages/desktop-electron + env: + OPENCODE_VERSION: ${{ needs.version.outputs.version }} + OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }} + RUST_TARGET: ${{ matrix.settings.target }} + GH_TOKEN: ${{ github.token }} + GITHUB_RUN_ID: ${{ github.run_id }} + + - name: Build + run: bun run build + working-directory: packages/desktop-electron + env: + OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }} + + - name: Package and publish + if: needs.version.outputs.release + run: npx electron-builder ${{ matrix.settings.platform_flag }} --publish always --config electron-builder.config.ts + working-directory: packages/desktop-electron + timeout-minutes: 60 + env: + OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }} + GH_TOKEN: ${{ steps.committer.outputs.token }} + CSC_LINK: ${{ secrets.APPLE_CERTIFICATE }} + CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_API_KEY: ${{ runner.temp }}/apple-api-key.p8 + APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY }} + APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} + + - name: Package (no publish) + if: ${{ !needs.version.outputs.release }} + run: npx electron-builder ${{ matrix.settings.platform_flag }} --publish never --config electron-builder.config.ts + working-directory: packages/desktop-electron + timeout-minutes: 60 + env: + OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }} + + - uses: actions/upload-artifact@v4 + with: + name: opencode-electron-${{ matrix.settings.target }} + path: packages/desktop-electron/dist/* + + - uses: actions/upload-artifact@v4 + if: needs.version.outputs.release + with: + name: latest-yml-${{ matrix.settings.target }} + path: packages/desktop-electron/dist/latest*.yml + publish: needs: - version - build-cli - build-tauri + - build-electron runs-on: blacksmith-4vcpu-ubuntu-2404 steps: - uses: actions/checkout@v3 @@ -281,6 +399,12 @@ jobs: name: opencode-cli path: packages/opencode/dist + - uses: actions/download-artifact@v4 + if: needs.version.outputs.release + with: + pattern: latest-yml-* + path: /tmp/latest-yml + - name: Cache apt packages (AUR) uses: actions/cache@v4 with: @@ -308,3 +432,4 @@ jobs: GITHUB_TOKEN: ${{ steps.committer.outputs.token }} GH_REPO: ${{ needs.version.outputs.repo }} NPM_CONFIG_PROVENANCE: false + LATEST_YML_DIR: /tmp/latest-yml diff --git a/.opencode/glossary/tr.md b/.opencode/glossary/tr.md new file mode 100644 index 0000000000..72b1cdfb40 --- /dev/null +++ b/.opencode/glossary/tr.md @@ -0,0 +1,38 @@ +# tr Glossary + +## Sources + +- PR #15835: https://github.com/anomalyco/opencode/pull/15835 + +## Do Not Translate (Locale Additions) + +- `OpenCode` (preserve casing in prose, docs, and UI copy) +- Keep lowercase `opencode` in commands, package names, paths, URLs, and other exact identifiers +- `` stays the literal key token in code blocks; use `Tab` for the nearby explanatory label in prose +- Commands, flags, file paths, and code literals (keep exactly as written) + +## Preferred Terms + +These are PR-backed wording preferences and may evolve. + +| English / Context | Preferred | Notes | +| ------------------------- | --------------------------------------- | ------------------------------------------------------------- | +| available in beta | `beta olarak mevcut` | Prefer this over `beta olarak kullanılabilir` | +| privacy-first | `Gizlilik öncelikli tasarlandı` | Prefer this over `Önce gizlilik için tasarlandı` | +| connect your local models | `yerel modellerinizi bağlayabilirsiniz` | Use the fuller, more direct action phrase | +| `` key label | `Tab` | Use `Tab` in prose; keep `` in literal UI or code blocks | +| cross-platform | `cross-platform (tüm platformlarda)` | Keep the English term, add a short clarification when helpful | + +## Guidance + +- Prefer natural Turkish phrasing over literal translation +- Merge broken sentence fragments into one clear sentence when the source is a single thought +- Keep product naming consistent: `OpenCode` in prose, `opencode` only for exact technical identifiers +- When an English technical term is intentionally kept, add a short Turkish clarification only if it improves readability + +## Avoid + +- Avoid `beta olarak kullanılabilir` when `beta olarak mevcut` fits +- Avoid `Önce gizlilik için tasarlandı`; use the more natural reviewed wording instead +- Avoid `Sekme` for the translated key label in prose when referring to `` +- Avoid changing `opencode` to `OpenCode` inside commands, URLs, package names, or code literals diff --git a/AGENTS.md b/AGENTS.md index 758714d10a..2158d73af1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,6 +20,17 @@ Prefer single word names for variables and functions. Only use multiple words if necessary. +### Naming Enforcement (Read This) + +THIS RULE IS MANDATORY FOR AGENT WRITTEN CODE. + +- Use single word names by default for new locals, params, and helper functions. +- Multi-word names are allowed only when a single word would be unclear or ambiguous. +- Do not introduce new camelCase compounds when a short single-word alternative is clear. +- Before finishing edits, review touched lines and shorten newly introduced identifiers where possible. +- Good short names to prefer: `pid`, `cfg`, `err`, `opts`, `dir`, `root`, `child`, `state`, `timeout`. +- Examples to avoid unless truly required: `inputPID`, `existingClient`, `connectTimeout`, `workerPath`. + ```ts // Good const foo = 1 diff --git a/README.ar.md b/README.ar.md index 987cb3234e..865fecb22b 100644 --- a/README.ar.md +++ b/README.ar.md @@ -27,6 +27,7 @@ 日本語 | Polski | Русский | + Bosanski | العربية | Norsk | Português (Brasil) | diff --git a/bun.lock b/bun.lock index f9f48eddd0..badb0410ab 100644 --- a/bun.lock +++ b/bun.lock @@ -25,7 +25,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -75,7 +75,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -109,7 +109,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -136,7 +136,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -160,7 +160,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -184,7 +184,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -215,9 +215,39 @@ "vite": "catalog:", }, }, + "packages/desktop-electron": { + "name": "@opencode-ai/desktop-electron", + "version": "1.2.6", + "dependencies": { + "@opencode-ai/app": "workspace:*", + "@opencode-ai/ui": "workspace:*", + "@solid-primitives/i18n": "2.2.1", + "@solid-primitives/storage": "catalog:", + "@solidjs/meta": "catalog:", + "@solidjs/router": "0.15.4", + "electron-log": "^5", + "electron-store": "^10", + "electron-updater": "^6", + "electron-window-state": "^5.0.3", + "marked": "^15", + "solid-js": "catalog:", + "tree-kill": "^1.2.2", + }, + "devDependencies": { + "@actions/artifact": "4.0.0", + "@types/bun": "catalog:", + "@types/node": "catalog:", + "@typescript/native-preview": "catalog:", + "electron": "40.4.1", + "electron-builder": "^26", + "electron-vite": "^5", + "typescript": "~5.6.2", + "vite": "catalog:", + }, + }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -246,7 +276,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -262,7 +292,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.2.15", + "version": "1.2.16", "bin": { "opencode": "./bin/opencode", }, @@ -304,8 +334,8 @@ "@opencode-ai/sdk": "workspace:*", "@opencode-ai/util": "workspace:*", "@openrouter/ai-sdk-provider": "1.5.4", - "@opentui/core": "0.1.81", - "@opentui/solid": "0.1.81", + "@opentui/core": "0.1.86", + "@opentui/solid": "0.1.86", "@parcel/watcher": "2.5.1", "@pierre/diffs": "catalog:", "@solid-primitives/event-bus": "1.1.2", @@ -376,7 +406,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -396,7 +426,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.2.15", + "version": "1.2.16", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -407,7 +437,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -423,17 +453,18 @@ "devDependencies": { "@opencode-ai/ui": "workspace:*", "@solidjs/meta": "catalog:", - "@storybook/addon-a11y": "^10.2.10", - "@storybook/addon-docs": "^10.2.10", - "@storybook/addon-links": "^10.2.10", - "@storybook/addon-onboarding": "^10.2.10", - "@storybook/addon-vitest": "^10.2.10", + "@storybook/addon-a11y": "^10.2.13", + "@storybook/addon-docs": "^10.2.13", + "@storybook/addon-links": "^10.2.13", + "@storybook/addon-onboarding": "^10.2.13", + "@storybook/addon-vitest": "^10.2.13", + "@tailwindcss/vite": "catalog:", "@tsconfig/node22": "catalog:", "@types/node": "catalog:", "@types/react": "18.0.25", "react": "18.2.0", "solid-js": "catalog:", - "storybook": "^10.2.10", + "storybook": "^10.2.13", "storybook-solidjs-vite": "^10.0.9", "typescript": "catalog:", "vite": "catalog:", @@ -441,7 +472,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -452,7 +483,6 @@ "@solid-primitives/media": "2.3.3", "@solid-primitives/resize-observer": "2.1.3", "@solidjs/meta": "catalog:", - "@typescript/native-preview": "catalog:", "dompurify": "3.3.1", "fuzzysort": "catalog:", "katex": "0.16.27", @@ -461,6 +491,9 @@ "marked-katex-extension": "5.1.6", "marked-shiki": "catalog:", "morphdom": "2.7.8", + "motion": "12.34.5", + "motion-dom": "12.34.3", + "motion-utils": "12.29.2", "remeda": "catalog:", "shiki": "catalog:", "solid-js": "catalog:", @@ -474,6 +507,7 @@ "@types/bun": "catalog:", "@types/katex": "0.16.7", "@types/luxon": "catalog:", + "@typescript/native-preview": "catalog:", "tailwindcss": "catalog:", "typescript": "catalog:", "vite": "catalog:", @@ -483,7 +517,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "zod": "catalog:", }, @@ -494,7 +528,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.2.15", + "version": "1.2.16", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", @@ -527,6 +561,7 @@ }, }, "trustedDependencies": [ + "electron", "esbuild", "web-tree-sitter", "tree-sitter-bash", @@ -545,7 +580,7 @@ "@kobalte/core": "0.13.11", "@octokit/rest": "22.0.0", "@openauthjs/openauth": "0.0.0-20250322224806", - "@pierre/diffs": "1.1.0-beta.13", + "@pierre/diffs": "1.1.0-beta.18", "@playwright/test": "1.51.0", "@solid-primitives/storage": "4.3.3", "@solidjs/meta": "0.29.4", @@ -583,6 +618,8 @@ "zod": "4.1.8", }, "packages": { + "7zip-bin": ["7zip-bin@5.2.0", "", {}, "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A=="], + "@actions/artifact": ["@actions/artifact@5.0.1", "", { "dependencies": { "@actions/core": "^2.0.0", "@actions/github": "^6.0.1", "@actions/http-client": "^3.0.0", "@azure/storage-blob": "^12.29.1", "@octokit/core": "^5.2.1", "@octokit/plugin-request-log": "^1.0.4", "@octokit/plugin-retry": "^3.0.9", "@octokit/request": "^8.4.1", "@octokit/request-error": "^5.1.1", "@protobuf-ts/plugin": "^2.2.3-alpha.1", "archiver": "^7.0.1", "jwt-decode": "^3.1.2", "unzip-stream": "^0.3.1" } }, "sha512-dHJ5rHduhCKUikKTT9eXeWoUvfKia3IjR1sO/VTAV3DVAL4yMTRnl2iO5mcfiBjySHLwPNezwENAVskKYU5ymw=="], "@actions/core": ["@actions/core@1.11.1", "", { "dependencies": { "@actions/exec": "^1.1.1", "@actions/http-client": "^2.0.1" } }, "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A=="], @@ -855,6 +892,8 @@ "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A=="], + "@babel/plugin-transform-arrow-functions": ["@babel/plugin-transform-arrow-functions@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA=="], + "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.28.6", "", { "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA=="], "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="], @@ -907,12 +946,30 @@ "@ctrl/tinycolor": ["@ctrl/tinycolor@4.2.0", "", {}, "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A=="], + "@develar/schema-utils": ["@develar/schema-utils@2.6.5", "", { "dependencies": { "ajv": "^6.12.0", "ajv-keywords": "^3.4.1" } }, "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig=="], + "@dimforge/rapier2d-simd-compat": ["@dimforge/rapier2d-simd-compat@0.17.3", "", {}, "sha512-bijvwWz6NHsNj5e5i1vtd3dU2pDhthSaTUZSh14DUGGKJfw8eMnlWZsxwHBxB/a3AXVNDjL9abuHw1k9FGR+jg=="], "@dot/log": ["@dot/log@0.1.5", "", { "dependencies": { "chalk": "^4.1.2", "loglevelnext": "^6.0.0", "p-defer": "^3.0.0" } }, "sha512-ECraEVJWv2f2mWK93lYiefUkphStVlKD6yKDzisuoEmxuLKrxO9iGetHK2DoEAkj7sxjE886n0OUVVCUx0YPNg=="], "@drizzle-team/brocli": ["@drizzle-team/brocli@0.11.0", "", {}, "sha512-hD3pekGiPg0WPCCGAZmusBBJsDqGUR66Y452YgQsZOnkdQ7ViEPKuyP4huUGEZQefp8g34RRodXYmJ2TbCH+tg=="], + "@electron/asar": ["@electron/asar@3.4.1", "", { "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", "minimatch": "^3.0.4" }, "bin": { "asar": "bin/asar.js" } }, "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA=="], + + "@electron/fuses": ["@electron/fuses@1.8.0", "", { "dependencies": { "chalk": "^4.1.1", "fs-extra": "^9.0.1", "minimist": "^1.2.5" }, "bin": { "electron-fuses": "dist/bin.js" } }, "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw=="], + + "@electron/get": ["@electron/get@2.0.3", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ=="], + + "@electron/notarize": ["@electron/notarize@2.5.0", "", { "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.1", "promise-retry": "^2.0.1" } }, "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A=="], + + "@electron/osx-sign": ["@electron/osx-sign@1.3.3", "", { "dependencies": { "compare-version": "^0.1.2", "debug": "^4.3.4", "fs-extra": "^10.0.0", "isbinaryfile": "^4.0.8", "minimist": "^1.2.6", "plist": "^3.0.5" }, "bin": { "electron-osx-flat": "bin/electron-osx-flat.js", "electron-osx-sign": "bin/electron-osx-sign.js" } }, "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg=="], + + "@electron/rebuild": ["@electron/rebuild@4.0.3", "", { "dependencies": { "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.1.1", "detect-libc": "^2.0.1", "got": "^11.7.0", "graceful-fs": "^4.2.11", "node-abi": "^4.2.0", "node-api-version": "^0.2.1", "node-gyp": "^11.2.0", "ora": "^5.1.0", "read-binary-file-arch": "^1.0.6", "semver": "^7.3.5", "tar": "^7.5.6", "yargs": "^17.0.1" }, "bin": { "electron-rebuild": "lib/cli.js" } }, "sha512-u9vpTHRMkOYCs/1FLiSVAFZ7FbjsXK+bQuzviJZa+lG7BHZl1nz52/IcGvwa3sk80/fc3llutBkbCq10Vh8WQA=="], + + "@electron/universal": ["@electron/universal@2.0.3", "", { "dependencies": { "@electron/asar": "^3.3.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "dir-compare": "^4.2.0", "fs-extra": "^11.1.1", "minimatch": "^9.0.3", "plist": "^3.1.0" } }, "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g=="], + + "@electron/windows-sign": ["@electron/windows-sign@1.2.2", "", { "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", "fs-extra": "^11.1.1", "minimist": "^1.2.8", "postject": "^1.0.0-alpha.6" }, "bin": { "electron-windows-sign": "bin/electron-windows-sign.js" } }, "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ=="], + "@emmetio/abbreviation": ["@emmetio/abbreviation@2.3.3", "", { "dependencies": { "@emmetio/scanner": "^1.0.4" } }, "sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA=="], "@emmetio/css-abbreviation": ["@emmetio/css-abbreviation@2.1.8", "", { "dependencies": { "@emmetio/scanner": "^1.0.4" } }, "sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw=="], @@ -1229,6 +1286,10 @@ "@lukeed/ms": ["@lukeed/ms@2.0.2", "", {}, "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA=="], + "@malept/cross-spawn-promise": ["@malept/cross-spawn-promise@2.0.0", "", { "dependencies": { "cross-spawn": "^7.0.1" } }, "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg=="], + + "@malept/flatpak-bundler": ["@malept/flatpak-bundler@0.4.0", "", { "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.0", "lodash": "^4.17.15", "tmp-promise": "^3.0.2" } }, "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q=="], + "@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="], "@mdx-js/react": ["@mdx-js/react@3.1.1", "", { "dependencies": { "@types/mdx": "^2.0.0" }, "peerDependencies": { "@types/react": ">=16", "react": ">=16" } }, "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw=="], @@ -1257,6 +1318,10 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + "@npmcli/agent": ["@npmcli/agent@3.0.0", "", { "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^10.0.1", "socks-proxy-agent": "^8.0.3" } }, "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q=="], + + "@npmcli/fs": ["@npmcli/fs@4.0.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q=="], + "@octokit/auth-app": ["@octokit/auth-app@8.0.1", "", { "dependencies": { "@octokit/auth-oauth-app": "^9.0.1", "@octokit/auth-oauth-user": "^6.0.0", "@octokit/request": "^10.0.2", "@octokit/request-error": "^7.0.0", "@octokit/types": "^14.0.0", "toad-cache": "^3.7.0", "universal-github-app-jwt": "^2.2.0", "universal-user-agent": "^7.0.0" } }, "sha512-P2J5pB3pjiGwtJX4WqJVYCtNkcZ+j5T2Wm14aJAEIC3WJOrv12jvBley3G1U/XI8q9o1A7QMG54LiFED2BiFlg=="], "@octokit/auth-oauth-app": ["@octokit/auth-oauth-app@9.0.3", "", { "dependencies": { "@octokit/auth-oauth-device": "^8.0.3", "@octokit/auth-oauth-user": "^6.0.2", "@octokit/request": "^10.0.6", "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-+yoFQquaF8OxJSxTb7rnytBIC2ZLbLqA/yb71I4ZXT9+Slw4TziV9j/kyGhUFRRTF2+7WlnIWsePZCWHs+OGjg=="], @@ -1315,6 +1380,8 @@ "@opencode-ai/desktop": ["@opencode-ai/desktop@workspace:packages/desktop"], + "@opencode-ai/desktop-electron": ["@opencode-ai/desktop-electron@workspace:packages/desktop-electron"], + "@opencode-ai/enterprise": ["@opencode-ai/enterprise@workspace:packages/enterprise"], "@opencode-ai/function": ["@opencode-ai/function@workspace:packages/function"], @@ -1341,21 +1408,21 @@ "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], - "@opentui/core": ["@opentui/core@0.1.81", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.81", "@opentui/core-darwin-x64": "0.1.81", "@opentui/core-linux-arm64": "0.1.81", "@opentui/core-linux-x64": "0.1.81", "@opentui/core-win32-arm64": "0.1.81", "@opentui/core-win32-x64": "0.1.81", "bun-webgpu": "0.1.5", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-ooFjkkQ80DDC4X5eLvH8dBcLAtWwGp9RTaWsaeWet3GOv4N0SDcN8mi1XGhYnUlTuxmofby5eQrPegjtWHODlA=="], + "@opentui/core": ["@opentui/core@0.1.86", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.86", "@opentui/core-darwin-x64": "0.1.86", "@opentui/core-linux-arm64": "0.1.86", "@opentui/core-linux-x64": "0.1.86", "@opentui/core-win32-arm64": "0.1.86", "@opentui/core-win32-x64": "0.1.86", "bun-webgpu": "0.1.5", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-3tRLbI9ADrQE1jEEn4x2aJexEOQZkv9Emk2BixMZqxfVhz2zr2SxtpimDAX0vmZK3+GnWAwBWxuaCAsxZpY4+w=="], - "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.81", "", { "os": "darwin", "cpu": "arm64" }, "sha512-I3Ry5JbkSQXs2g1me8yYr0v3CUcIIfLHzbWz9WMFla8kQDSa+HOr8IpZbqZDeIFgOVzolAXBmZhg0VJI3bZ7MA=="], + "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.86", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Zp7q64+d+Dcx6YrH3mRcnHq8EOBnrfc1RvjgSWLhpXr49hY6LzuhqpfZM57aGErPYlR+ff8QM6e5FUkFnDfyjw=="], - "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.81", "", { "os": "darwin", "cpu": "x64" }, "sha512-CrtNKu41D6+bOQdUOmDX4Q3hTL6p+sT55wugPzbDq7cdqFZabCeguBAyOlvRl2g2aJ93kmOWW6MXG0bPPklEFg=="], + "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.86", "", { "os": "darwin", "cpu": "x64" }, "sha512-NcxfjCJm1kLnTMVOpAPdRYNi8W8XdAXNa6N7i9khiVFrl2v5KRQfUjbrSOUYVxFJNc3jKFG6rsn3jEApvn92qA=="], - "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.81", "", { "os": "linux", "cpu": "arm64" }, "sha512-FJw9zmJop9WiMvtT07nSrfBLPLqskxL6xfV3GNft0mSYV+C3hdJ0qkiczGSHUX/6V7fmouM84RWwmY53Rb6hYQ=="], + "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.86", "", { "os": "linux", "cpu": "arm64" }, "sha512-EDHAvqSOr8CXzbDvo1aE5blJ6wu1aSbR2LqoXtoeXHemr2T2W42D2TdIWewG6K+/BuRbzZnqt9wnYFBksLW6lw=="], - "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.81", "", { "os": "linux", "cpu": "x64" }, "sha512-Rj2AFIiuWI0BEMIvh/Jeuxty9Gp5ZhLuQU7ZHJJhojKo/mpBpMs9X+5kwZPZya/tyR8uVDAVyB6AOLkhdRW5lw=="], + "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.86", "", { "os": "linux", "cpu": "x64" }, "sha512-VBaBkVdQDxYV4WcKjb+jgyMS5PiVHepvfaoKWpz1Bq+J01xXW4XPcXyPGkgR1+2R93KzaugEnLscTW4mWtLHlQ=="], - "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.81", "", { "os": "win32", "cpu": "arm64" }, "sha512-AiZB+mZ1cVr8plAPrPT98e3kw6D0OdOSe2CQYLgJRbfRlPqq3jl26lHPzDb3ZO2OR0oVGRPJvXraus939mvoiQ=="], + "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.86", "", { "os": "win32", "cpu": "arm64" }, "sha512-xKbT7sEKYKGwUPkoqmLfHjbJU+vwHPDwf/r/mIunL41JXQBB35CSZ3/QgIwpp2kkteu7oE1tdBdg15ogUU4OMg=="], - "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.81", "", { "os": "win32", "cpu": "x64" }, "sha512-l8R2Ni1CR4eHi3DTmSkEL/EjHAtOZ/sndYs3VVw+Ej2esL3Mf0W7qSO5S0YNBanz2VXZhbkmM6ERm9keH8RD3w=="], + "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.86", "", { "os": "win32", "cpu": "x64" }, "sha512-HRfgAUlcu71/MrtgfX4Gj7PsDtfXZiuC506Pkn1OnRN1Xomcu10BVRDweUa0/g8ldU9i9kLjMGGnpw6/NjaBFg=="], - "@opentui/solid": ["@opentui/solid@0.1.81", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.81", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-QRjS0wPuIhBRdY8tpG3yprCM4ZnOxWWHTuaZ4hhia2wFZygf7Ome6EuZnLXmtuOQjkjCwu0if8Yik6toc6QylA=="], + "@opentui/solid": ["@opentui/solid@0.1.86", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.86", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-pOZC9dlZIH+bpstVVZ2AvYukBnslZTKSl/y5H8FWcMTHGv/BzpGxXBxstL65E/IQASqPFbvFcs7yMRzdLhynmA=="], "@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="], @@ -1469,7 +1536,9 @@ "@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="], - "@pierre/diffs": ["@pierre/diffs@1.1.0-beta.13", "", { "dependencies": { "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-D35rxDu5V7XHX5aVGU6PF12GhscL+I+9QYgxK/i3h0d2XSirAxDdVNm49aYwlOhgmdvL0NbS1IHxPswVB5yJvw=="], + "@pierre/diffs": ["@pierre/diffs@1.1.0-beta.18", "", { "dependencies": { "@pierre/theme": "0.0.22", "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-7ZF3YD9fxdbYsPnltz5cUqHacN7ztp8RX/fJLxwv8wIEORpP4+7dHz1h/qx3o4EW2xUrIhmbM8ImywLasB787Q=="], + + "@pierre/theme": ["@pierre/theme@0.0.22", "", {}, "sha512-ePUIdQRNGjrveELTU7fY89Xa7YGHHEy5Po5jQy/18lm32eRn96+tnYJEtFooGdffrx55KBUtOXfvVy/7LDFFhA=="], "@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="], @@ -1629,7 +1698,7 @@ "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], - "@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="], + "@sindresorhus/is": ["@sindresorhus/is@4.6.0", "", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="], "@slack/bolt": ["@slack/bolt@3.22.0", "", { "dependencies": { "@slack/logger": "^4.0.0", "@slack/oauth": "^2.6.3", "@slack/socket-mode": "^1.3.6", "@slack/types": "^2.13.0", "@slack/web-api": "^6.13.0", "@types/express": "^4.16.1", "@types/promise.allsettled": "^1.0.3", "@types/tsscmp": "^1.0.0", "axios": "^1.7.4", "express": "^4.21.0", "path-to-regexp": "^8.1.0", "promise.allsettled": "^1.0.2", "raw-body": "^2.3.3", "tsscmp": "^1.0.6" } }, "sha512-iKDqGPEJDnrVwxSVlFW6OKTkijd7s4qLBeSufoBsTM0reTyfdp/5izIQVkxNfzjHi3o6qjdYbRXkYad5HBsBog=="], @@ -1801,30 +1870,32 @@ "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], - "@storybook/addon-a11y": ["@storybook/addon-a11y@10.2.10", "", { "dependencies": { "@storybook/global": "^5.0.0", "axe-core": "^4.2.0" }, "peerDependencies": { "storybook": "^10.2.10" } }, "sha512-1S9pDXgvbHhBStGarCvfJ3/rfcaiAcQHRhuM3Nk4WGSIYtC1LCSRuzYdDYU0aNRpdCbCrUA7kUCbqvIE3tH+3Q=="], + "@storybook/addon-a11y": ["@storybook/addon-a11y@10.2.13", "", { "dependencies": { "@storybook/global": "^5.0.0", "axe-core": "^4.2.0" }, "peerDependencies": { "storybook": "^10.2.13" } }, "sha512-zuR1n1xgWoieEnr6E5xdTR40BI61IBQahgmsRpTvqRffL3mxAs5aFoORDmA5pZWI2LE9URdMkY85h218ijuLiw=="], - "@storybook/addon-docs": ["@storybook/addon-docs@10.2.10", "", { "dependencies": { "@mdx-js/react": "^3.0.0", "@storybook/csf-plugin": "10.2.10", "@storybook/icons": "^2.0.1", "@storybook/react-dom-shim": "10.2.10", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^10.2.10" } }, "sha512-2wIYtdvZIzPbQ5194M5Igpy8faNbQ135nuO5ZaZ2VuttqGr+IJcGnDP42zYwbAsGs28G8ohpkbSgIzVyJWUhPQ=="], + "@storybook/addon-docs": ["@storybook/addon-docs@10.2.13", "", { "dependencies": { "@mdx-js/react": "^3.0.0", "@storybook/csf-plugin": "10.2.13", "@storybook/icons": "^2.0.1", "@storybook/react-dom-shim": "10.2.13", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^10.2.13" } }, "sha512-puMxpJbt/CuodLIbKDxWrW1ZgADYomfNHWEKp2d2l2eJjp17rADx0h3PABuNbX+YHbJwYcDdqluSnQwMysFEOA=="], - "@storybook/addon-links": ["@storybook/addon-links@10.2.10", "", { "dependencies": { "@storybook/global": "^5.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "storybook": "^10.2.10" }, "optionalPeers": ["react"] }, "sha512-oo9Xx4/2OVJtptXKpqH4ySri7ZuBdiSOXlZVGejEfLa0Jeajlh/KIlREpGvzPPOqUVT7dSddWzBjJmJUyQC3ew=="], + "@storybook/addon-links": ["@storybook/addon-links@10.2.13", "", { "dependencies": { "@storybook/global": "^5.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "storybook": "^10.2.13" }, "optionalPeers": ["react"] }, "sha512-8wnAomGiHaUpNIc+lOzmazTrebxa64z9rihIbM/Q59vkOImHQNkGp7KP/qNgJA4GPTFtu8+fLjX2qCoAQPM0jQ=="], - "@storybook/addon-onboarding": ["@storybook/addon-onboarding@10.2.10", "", { "peerDependencies": { "storybook": "^10.2.10" } }, "sha512-DkzZQTXHp99SpHMIQ5plbbHcs4EWVzWhLXlW+icA8sBlKo5Bwj540YcOApKbqB0m/OzWprsznwN7Kv4vfvHu4w=="], + "@storybook/addon-onboarding": ["@storybook/addon-onboarding@10.2.13", "", { "peerDependencies": { "storybook": "^10.2.13" } }, "sha512-kw2GgIY67UR8YXKfuVS0k+mfWL1joNQHeSe5DlDL4+7qbgp9zfV6cRJ199BMdfRAQNMzQoxHgRUcAMAqs3Rkpw=="], - "@storybook/addon-vitest": ["@storybook/addon-vitest@10.2.10", "", { "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^2.0.1" }, "peerDependencies": { "@vitest/browser": "^3.0.0 || ^4.0.0", "@vitest/browser-playwright": "^4.0.0", "@vitest/runner": "^3.0.0 || ^4.0.0", "storybook": "^10.2.10", "vitest": "^3.0.0 || ^4.0.0" }, "optionalPeers": ["@vitest/browser", "@vitest/browser-playwright", "@vitest/runner", "vitest"] }, "sha512-U2oHw+Ar+Xd06wDTB74VlujhIIW89OHThpJjwgqgM6NWrOC/XLllJ53ILFDyREBkMwpBD7gJQIoQpLEcKBIEhw=="], + "@storybook/addon-vitest": ["@storybook/addon-vitest@10.2.13", "", { "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^2.0.1" }, "peerDependencies": { "@vitest/browser": "^3.0.0 || ^4.0.0", "@vitest/browser-playwright": "^4.0.0", "@vitest/runner": "^3.0.0 || ^4.0.0", "storybook": "^10.2.13", "vitest": "^3.0.0 || ^4.0.0" }, "optionalPeers": ["@vitest/browser", "@vitest/browser-playwright", "@vitest/runner", "vitest"] }, "sha512-qQD3xzxc31cQHS0loF9enGWi5sgA6zBTbaJ0HuSUNGO81iwfLSALh8L/1vrD5NfN2vlBeUMTsgv3EkCuLfe9EQ=="], "@storybook/builder-vite": ["@storybook/builder-vite@10.2.10", "", { "dependencies": { "@storybook/csf-plugin": "10.2.10", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^10.2.10", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-Wd6CYL7LvRRNiXMz977x9u/qMm7nmMw/7Dow2BybQo+Xbfy1KhVjIoZ/gOiG515zpojSozctNrJUbM0+jH1jwg=="], - "@storybook/csf-plugin": ["@storybook/csf-plugin@10.2.10", "", { "dependencies": { "unplugin": "^2.3.5" }, "peerDependencies": { "esbuild": "*", "rollup": "*", "storybook": "^10.2.10", "vite": "*", "webpack": "*" }, "optionalPeers": ["esbuild", "rollup", "vite", "webpack"] }, "sha512-aFvgaNDAnKMjuyhPK5ialT22pPqMN0XfPBNPeeNVPYztngkdKBa8WFqF/umDd47HxAjebq+vn6uId1xHyOHH3g=="], + "@storybook/csf-plugin": ["@storybook/csf-plugin@10.2.13", "", { "dependencies": { "unplugin": "^2.3.5" }, "peerDependencies": { "esbuild": "*", "rollup": "*", "storybook": "^10.2.13", "vite": "*", "webpack": "*" }, "optionalPeers": ["esbuild", "rollup", "vite", "webpack"] }, "sha512-gUCR7PmyrWYj3dIJJgxOm25dcXFolPIUPmug3z90Aaon7YPXw3pUN+dNDx8KqDJqRK1WDIB4HaefgYZIm5V7iA=="], "@storybook/global": ["@storybook/global@5.0.0", "", {}, "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ=="], "@storybook/icons": ["@storybook/icons@2.0.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-/smVjw88yK3CKsiuR71vNgWQ9+NuY2L+e8X7IMrFjexjm6ZR8ULrV2DRkTA61aV6ryefslzHEGDInGpnNeIocg=="], - "@storybook/react-dom-shim": ["@storybook/react-dom-shim@10.2.10", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "storybook": "^10.2.10" } }, "sha512-TmBrhyLHn8B8rvDHKk5uW5BqzO1M1T+fqFNWg88NIAJOoyX4Uc90FIJjDuN1OJmWKGwB5vLmPwaKBYsTe1yS+w=="], + "@storybook/react-dom-shim": ["@storybook/react-dom-shim@10.2.13", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "storybook": "^10.2.13" } }, "sha512-ZSduoB10qTI0V9z22qeULmQLsvTs8d/rtJi03qbVxpPiMRor86AmyAaBrfhGGmWBxWQZpOGQQm6yIT2YLoPs7w=="], "@stripe/stripe-js": ["@stripe/stripe-js@8.6.1", "", {}, "sha512-UJ05U2062XDgydbUcETH1AoRQLNhigQ2KmDn1BG8sC3xfzu6JKg95Qt6YozdzFpxl1Npii/02m2LEWFt1RYjVA=="], "@swc/helpers": ["@swc/helpers@0.5.18", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ=="], + "@szmarczak/http-timer": ["@szmarczak/http-timer@4.0.6", "", { "dependencies": { "defer-to-connect": "^2.0.0" } }, "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w=="], + "@tailwindcss/node": ["@tailwindcss/node@4.1.11", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.11" } }, "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q=="], "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.11", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.11", "@tailwindcss/oxide-darwin-arm64": "4.1.11", "@tailwindcss/oxide-darwin-x64": "4.1.11", "@tailwindcss/oxide-freebsd-x64": "4.1.11", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", "@tailwindcss/oxide-linux-x64-musl": "4.1.11", "@tailwindcss/oxide-wasm32-wasi": "4.1.11", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" } }, "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg=="], @@ -1945,6 +2016,8 @@ "@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="], + "@types/cacheable-request": ["@types/cacheable-request@6.0.3", "", { "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", "@types/node": "*", "@types/responselike": "^1.0.0" } }, "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw=="], + "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], @@ -1963,8 +2036,12 @@ "@types/fontkit": ["@types/fontkit@2.0.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-wN+8bYxIpJf+5oZdrdtaX04qUuWHcKxcDEgRS9Qm9ZClSHjzEn13SxUC+5eRM+4yXIeTYk8mTzLAWGF64847ew=="], + "@types/fs-extra": ["@types/fs-extra@9.0.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA=="], + "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], + "@types/http-cache-semantics": ["@types/http-cache-semantics@4.2.0", "", {}, "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q=="], + "@types/http-errors": ["@types/http-errors@2.0.5", "", {}, "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg=="], "@types/is-stream": ["@types/is-stream@1.1.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-jkZatu4QVbR60mpIzjINmtS1ZF4a/FqdTUTBeQDVOQ2PYyidtwFKr0B5G6ERukKwliq+7mIXvxyppwzG5EgRYg=="], @@ -1977,6 +2054,8 @@ "@types/katex": ["@types/katex@0.16.7", "", {}, "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ=="], + "@types/keyv": ["@types/keyv@3.1.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg=="], + "@types/luxon": ["@types/luxon@3.7.1", "", {}, "sha512-H3iskjFIAn5SlJU7OuxUmTEpebK6TKB8rxZShDslBMZJ5u9S//KM1sbdAisiSrqwLQncVjnpi2OK2J51h+4lsg=="], "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], @@ -1999,6 +2078,8 @@ "@types/node-fetch": ["@types/node-fetch@2.6.13", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.4" } }, "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw=="], + "@types/plist": ["@types/plist@3.0.5", "", { "dependencies": { "@types/node": "*", "xmlbuilder": ">=11.0.1" } }, "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA=="], + "@types/promise.allsettled": ["@types/promise.allsettled@1.0.6", "", {}, "sha512-wA0UT0HeT2fGHzIFV9kWpYz5mdoyLxKrTgMdZQM++5h6pYAFH73HXcQhefg24nD1yivUFEn5KU+EF4b+CXJ4Wg=="], "@types/prop-types": ["@types/prop-types@15.7.15", "", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="], @@ -2011,6 +2092,8 @@ "@types/readable-stream": ["@types/readable-stream@4.0.23", "", { "dependencies": { "@types/node": "*" } }, "sha512-wwXrtQvbMHxCbBgjHaMGEmImFTQxxpfMOR/ZoQnXxB1woqkUbdLGFDgauo00Py9IudiaqSeiBiulSV9i6XIPig=="], + "@types/responselike": ["@types/responselike@1.0.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw=="], + "@types/retry": ["@types/retry@0.12.0", "", {}, "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA=="], "@types/sax": ["@types/sax@1.2.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A=="], @@ -2031,6 +2114,8 @@ "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], + "@types/verror": ["@types/verror@1.10.11", "", {}, "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg=="], + "@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="], "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], @@ -2039,6 +2124,8 @@ "@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="], + "@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="], + "@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20251207.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20251207.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20251207.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20251207.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20251207.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20251207.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20251207.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20251207.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-4QcRnzB0pi9rS0AOvg8kWbmuwHv5X7B2EXHbgcms9+56hsZ8SZrZjNgBJb2rUIodJ4kU5mrkj/xlTTT4r9VcpQ=="], "@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20251207.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-waWJnuuvkXh4WdpbTjYf7pyahJzx0ycesV2BylyHrE9OxU9FSKcD/cRLQYvbq3YcBSdF7sZwRLDBer7qTeLsYA=="], @@ -2097,6 +2184,8 @@ "@webgpu/types": ["@webgpu/types@0.1.54", "", {}, "sha512-81oaalC8LFrXjhsczomEQ0u3jG+TqE6V9QHLA8GNZq/Rnot0KDugu3LhSYSlie8tSdooAN1Hov05asrUUp9qgg=="], + "@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="], + "@zip.js/zip.js": ["@zip.js/zip.js@2.7.62", "", {}, "sha512-OaLvZ8j4gCkLn048ypkZu29KX30r8/OfFF2w4Jo5WXFr+J04J+lzJ5TKZBVgFXhlvSkqNFQdfnY1Q8TMTCyBVA=="], "abbrev": ["abbrev@2.0.0", "", {}, "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ=="], @@ -2127,6 +2216,8 @@ "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], + "ajv-keywords": ["ajv-keywords@3.5.2", "", { "peerDependencies": { "ajv": "^6.9.1" } }, "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="], + "ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="], "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], @@ -2143,6 +2234,10 @@ "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + "app-builder-bin": ["app-builder-bin@5.0.0-alpha.12", "", {}, "sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w=="], + + "app-builder-lib": ["app-builder-lib@26.8.1", "", { "dependencies": { "@develar/schema-utils": "~2.6.5", "@electron/asar": "3.4.1", "@electron/fuses": "^1.8.0", "@electron/get": "^3.0.0", "@electron/notarize": "2.5.0", "@electron/osx-sign": "1.3.3", "@electron/rebuild": "^4.0.3", "@electron/universal": "2.0.3", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "async-exit-hook": "^2.0.1", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chromium-pickle-js": "^0.2.0", "ci-info": "4.3.1", "debug": "^4.3.4", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", "electron-publish": "26.8.1", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", "isbinaryfile": "^5.0.0", "jiti": "^2.4.2", "js-yaml": "^4.1.0", "json5": "^2.2.3", "lazy-val": "^1.0.5", "minimatch": "^10.0.3", "plist": "3.1.0", "proper-lockfile": "^4.1.2", "resedit": "^1.7.0", "semver": "~7.7.3", "tar": "^7.5.7", "temp-file": "^3.4.0", "tiny-async-pool": "1.3.0", "which": "^5.0.0" }, "peerDependencies": { "dmg-builder": "26.8.1", "electron-builder-squirrel-windows": "26.8.1" } }, "sha512-p0Im/Dx5C4tmz8QEE1Yn4MkuPC8PrnlRneMhWJj7BBXQfNTJUshM/bp3lusdEsDbvvfJZpXWnYesgSLvwtM2Zw=="], + "archiver": ["archiver@7.0.1", "", { "dependencies": { "archiver-utils": "^5.0.2", "async": "^3.2.4", "buffer-crc32": "^1.0.0", "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", "tar-stream": "^3.0.0", "zip-stream": "^6.0.1" } }, "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ=="], "archiver-utils": ["archiver-utils@5.0.2", "", { "dependencies": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", "is-stream": "^2.0.1", "lazystream": "^1.0.0", "lodash": "^4.17.15", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA=="], @@ -2169,10 +2264,14 @@ "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="], + "assert-plus": ["assert-plus@1.0.0", "", {}, "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="], + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="], + "astral-regex": ["astral-regex@2.0.0", "", {}, "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="], + "astring": ["astring@1.9.0", "", { "bin": { "astring": "bin/astring" } }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="], "astro": ["astro@5.7.13", "", { "dependencies": { "@astrojs/compiler": "^2.11.0", "@astrojs/internal-helpers": "0.6.1", "@astrojs/markdown-remark": "6.3.1", "@astrojs/telemetry": "3.2.1", "@capsizecss/unpack": "^2.4.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", "acorn": "^8.14.1", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.2.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", "debug": "^4.4.0", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.3.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "magicast": "^0.3.5", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", "package-manager-detector": "^1.1.0", "picomatch": "^4.0.2", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.1", "shiki": "^3.2.1", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.12", "tsconfck": "^3.1.5", "ultrahtml": "^1.6.0", "unifont": "~0.5.0", "unist-util-visit": "^5.0.0", "unstorage": "^1.15.0", "vfile": "^6.0.3", "vite": "^6.3.4", "vitefu": "^1.0.6", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.1", "zod": "^3.24.2", "zod-to-json-schema": "^3.24.5", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-cRGq2llKOhV3XMcYwQpfBIUcssN6HEK5CRbcMxAfd9OcFhvWE7KUy50zLioAZVVl3AqgUTJoNTlmZfD2eG0G1w=="], @@ -2181,12 +2280,18 @@ "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], + "async-exit-hook": ["async-exit-hook@2.0.1", "", {}, "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw=="], + "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], + "at-least-node": ["at-least-node@1.0.0", "", {}, "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="], + "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="], + "atomically": ["atomically@2.1.1", "", { "dependencies": { "stubborn-fs": "^2.0.0", "when-exit": "^2.1.4" } }, "sha512-P4w9o2dqARji6P7MHprklbfiArZAWvo07yW7qs3pdljb3BWr12FIB7W+p0zJiuiVsUpRO0iZn1kFFcpPegg0tQ=="], + "autoprefixer": ["autoprefixer@10.4.24", "", { "dependencies": { "browserslist": "^4.28.1", "caniuse-lite": "^1.0.30001766", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw=="], "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], @@ -2255,6 +2360,8 @@ "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], + "boolean": ["boolean@3.2.0", "", {}, "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="], + "bottleneck": ["bottleneck@2.19.5", "", {}, "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="], "bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="], @@ -2279,6 +2386,10 @@ "buffers": ["buffers@0.1.1", "", {}, "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ=="], + "builder-util": ["builder-util@26.8.1", "", { "dependencies": { "7zip-bin": "~5.2.0", "@types/debug": "^4.1.6", "app-builder-bin": "5.0.0-alpha.12", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "cross-spawn": "^7.0.6", "debug": "^4.3.4", "fs-extra": "^10.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "js-yaml": "^4.1.0", "sanitize-filename": "^1.6.3", "source-map-support": "^0.5.19", "stat-mode": "^1.0.0", "temp-file": "^3.4.0", "tiny-async-pool": "1.3.0" } }, "sha512-pm1lTYbGyc90DHgCDO7eo8Rl4EqKLciayNbZqGziqnH9jrlKe8ZANGdityLZU+pJh16dfzjAx2xQq9McuIPEtw=="], + + "builder-util-runtime": ["builder-util-runtime@9.5.1", "", { "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" } }, "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ=="], + "bun-ffi-structs": ["bun-ffi-structs@0.1.2", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-Lh1oQAYHDcnesJauieA4UNkWGXY9hYck7OA5IaRwE3Bp6K2F2pJSNYqq+hIy7P3uOvo3km3oxS8304g5gDMl/w=="], "bun-pty": ["bun-pty@0.4.8", "", {}, "sha512-rO70Mrbr13+jxHHHu2YBkk2pNqrJE5cJn29WE++PUr+GFA0hq/VgtQPZANJ8dJo6d7XImvBk37Innt8GM7O28w=="], @@ -2301,6 +2412,14 @@ "c12": ["c12@3.3.3", "", { "dependencies": { "chokidar": "^5.0.0", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^17.2.3", "exsolve": "^1.0.8", "giget": "^2.0.0", "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "*" }, "optionalPeers": ["magicast"] }, "sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q=="], + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], + + "cacache": ["cacache@19.0.1", "", { "dependencies": { "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^12.0.0", "tar": "^7.4.3", "unique-filename": "^4.0.0" } }, "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ=="], + + "cacheable-lookup": ["cacheable-lookup@5.0.4", "", {}, "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA=="], + + "cacheable-request": ["cacheable-request@7.0.4", "", { "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", "normalize-url": "^6.0.1", "responselike": "^2.0.0" } }, "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg=="], + "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], @@ -2343,6 +2462,8 @@ "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], + "chromium-pickle-js": ["chromium-pickle-js@0.2.0", "", {}, "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw=="], + "ci-info": ["ci-info@4.4.0", "", {}, "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg=="], "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="], @@ -2353,14 +2474,20 @@ "cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="], + "cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="], + "cli-spinners": ["cli-spinners@3.4.0", "", {}, "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw=="], + "cli-truncate": ["cli-truncate@2.1.0", "", { "dependencies": { "slice-ansi": "^3.0.0", "string-width": "^4.2.0" } }, "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg=="], + "clipboardy": ["clipboardy@4.0.0", "", { "dependencies": { "execa": "^8.0.1", "is-wsl": "^3.1.0", "is64bit": "^2.0.0" } }, "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w=="], "cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="], "clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="], + "clone-response": ["clone-response@1.0.3", "", { "dependencies": { "mimic-response": "^1.0.0" } }, "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA=="], + "cloudflare": ["cloudflare@5.2.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-dVzqDpPFYR9ApEC9e+JJshFJZXcw4HzM8W+3DHzO5oy9+8rLC53G7x6fEf9A7/gSuSCxuvndzui5qJKftfIM9A=="], "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], @@ -2385,10 +2512,16 @@ "common-ancestor-path": ["common-ancestor-path@1.0.1", "", {}, "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w=="], + "compare-version": ["compare-version@0.1.2", "", {}, "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A=="], + "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=="], + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + "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=="], + "conf": ["conf@14.0.0", "", { "dependencies": { "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "atomically": "^2.0.3", "debounce-fn": "^6.0.0", "dot-prop": "^9.0.0", "env-paths": "^3.0.0", "json-schema-typed": "^8.0.1", "semver": "^7.7.2", "uint8array-extras": "^1.4.0" } }, "sha512-L6BuueHTRuJHQvQVc6YXYZRtN5vJUtOdCTLn0tRYYV5azfbAFcPghB5zEE40mVrV6w7slMTqUfkDomutIK14fw=="], + "confbox": ["confbox@0.2.4", "", {}, "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ=="], "config-chain": ["config-chain@1.1.13", "", { "dependencies": { "ini": "^1.3.4", "proto-list": "~1.2.1" } }, "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ=="], @@ -2407,14 +2540,18 @@ "cookie-signature": ["cookie-signature@1.0.7", "", {}, "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA=="], - "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], + "core-util-is": ["core-util-is@1.0.2", "", {}, "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="], "cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="], + "crc": ["crc@3.8.0", "", { "dependencies": { "buffer": "^5.1.0" } }, "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ=="], + "crc-32": ["crc-32@1.2.2", "", { "bin": { "crc32": "bin/crc32.njs" } }, "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="], "crc32-stream": ["crc32-stream@6.0.0", "", { "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^4.0.0" } }, "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g=="], + "cross-dirname": ["cross-dirname@0.1.0", "", {}, "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q=="], + "cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], @@ -2445,12 +2582,16 @@ "db0": ["db0@0.3.4", "", { "peerDependencies": { "@electric-sql/pglite": "*", "@libsql/client": "*", "better-sqlite3": "*", "drizzle-orm": "*", "mysql2": "*", "sqlite3": "*" }, "optionalPeers": ["@electric-sql/pglite", "@libsql/client", "better-sqlite3", "drizzle-orm", "mysql2", "sqlite3"] }, "sha512-RiXXi4WaNzPTHEOu8UPQKMooIbqOEyqA1t7Z6MsdxSCeb8iUC9ko3LcmsLmeUt2SM5bctfArZKkRQggKZz7JNw=="], + "debounce-fn": ["debounce-fn@6.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-rBMW+F2TXryBwB54Q0d8drNEI+TfoS9JpNTAoVpukbWEhjXQq4rySFYLaqXMFXwdv61Zb2OHtj5bviSoimqxRQ=="], + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "decimal.js": ["decimal.js@10.5.0", "", {}, "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw=="], "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="], + "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], + "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], @@ -2459,6 +2600,10 @@ "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="], + "defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="], + + "defer-to-connect": ["defer-to-connect@2.0.1", "", {}, "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="], + "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="], @@ -2483,6 +2628,8 @@ "detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], + "detect-node": ["detect-node@2.1.0", "", {}, "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="], + "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], "deterministic-object-hash": ["deterministic-object-hash@2.0.2", "", { "dependencies": { "base-64": "^1.0.0" } }, "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ=="], @@ -2497,12 +2644,18 @@ "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], + "dir-compare": ["dir-compare@4.2.0", "", { "dependencies": { "minimatch": "^3.0.5", "p-limit": "^3.1.0 " } }, "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ=="], + "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], "direction": ["direction@2.0.1", "", { "bin": { "direction": "cli.js" } }, "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA=="], "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], + "dmg-builder": ["dmg-builder@26.8.1", "", { "dependencies": { "app-builder-lib": "26.8.1", "builder-util": "26.8.1", "fs-extra": "^10.1.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" }, "optionalDependencies": { "dmg-license": "^1.0.11" } }, "sha512-glMJgnTreo8CFINujtAhCgN96QAqApDMZ8Vl1r8f0QT8QprvC1UCltV4CcWj20YoIyLZx6IUskaJZ0NV8fokcg=="], + + "dmg-license": ["dmg-license@1.0.11", "", { "dependencies": { "@types/plist": "^3.0.1", "@types/verror": "^1.10.3", "ajv": "^6.10.0", "crc": "^3.8.0", "iconv-corefoundation": "^1.1.7", "plist": "^3.0.4", "smart-buffer": "^4.0.2", "verror": "^1.10.0" }, "os": "darwin", "bin": { "dmg-license": "bin/dmg-license.js" } }, "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q=="], + "dns-packet": ["dns-packet@5.6.1", "", { "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" } }, "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw=="], "dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="], @@ -2521,7 +2674,9 @@ "dot-prop": ["dot-prop@8.0.2", "", { "dependencies": { "type-fest": "^3.8.0" } }, "sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ=="], - "dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="], + "dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], + + "dotenv-expand": ["dotenv-expand@11.0.7", "", { "dependencies": { "dotenv": "^16.4.5" } }, "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA=="], "drizzle-kit": ["drizzle-kit@1.0.0-beta.12-a5629fb", "", { "dependencies": { "@drizzle-team/brocli": "^0.11.0", "@js-temporal/polyfill": "^0.5.1", "esbuild": "^0.25.10", "tsx": "^4.20.6" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-l+p4QOMvPGYBYEE9NBlU7diu+NSlxuOUwi0I7i01Uj1PpfU0NxhPzaks/9q1MDw4FAPP8vdD0dOhoqosKtRWWQ=="], @@ -2539,8 +2694,30 @@ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], + "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="], + + "electron": ["electron@40.4.1", "", { "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^24.9.0", "extract-zip": "^2.0.1" }, "bin": { "electron": "cli.js" } }, "sha512-N1ZXybQZL8kYemO8vAeh9nrk4mSvqlAO8xs0QCHkXIvRnuB/7VGwEehjvQbsU5/f4bmTKpG+2GQERe/zmKpudQ=="], + + "electron-builder": ["electron-builder@26.8.1", "", { "dependencies": { "app-builder-lib": "26.8.1", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "ci-info": "^4.2.0", "dmg-builder": "26.8.1", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" }, "bin": { "electron-builder": "cli.js", "install-app-deps": "install-app-deps.js" } }, "sha512-uWhx1r74NGpCagG0ULs/P9Nqv2nsoo+7eo4fLUOB8L8MdWltq9odW/uuLXMFCDGnPafknYLZgjNX0ZIFRzOQAw=="], + + "electron-builder-squirrel-windows": ["electron-builder-squirrel-windows@26.8.1", "", { "dependencies": { "app-builder-lib": "26.8.1", "builder-util": "26.8.1", "electron-winstaller": "5.4.0" } }, "sha512-o288fIdgPLHA76eDrFADHPoo7VyGkDCYbLV1GzndaMSAVBoZrGvM9m2IehdcVMzdAZJ2eV9bgyissQXHv5tGzA=="], + + "electron-log": ["electron-log@5.4.3", "", {}, "sha512-sOUsM3LjZdugatazSQ/XTyNcw8dfvH1SYhXWiJyfYodAAKOZdHs0txPiLDXFzOZbhXgAgshQkshH2ccq0feyLQ=="], + + "electron-publish": ["electron-publish@26.8.1", "", { "dependencies": { "@types/fs-extra": "^9.0.11", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "form-data": "^4.0.5", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" } }, "sha512-q+jrSTIh/Cv4eGZa7oVR+grEJo/FoLMYBAnSL5GCtqwUpr1T+VgKB/dn1pnzxIxqD8S/jP1yilT9VrwCqINR4w=="], + + "electron-store": ["electron-store@10.1.0", "", { "dependencies": { "conf": "^14.0.0", "type-fest": "^4.41.0" } }, "sha512-oL8bRy7pVCLpwhmXy05Rh/L6O93+k9t6dqSw0+MckIc3OmCTZm6Mp04Q4f/J0rtu84Ky6ywkR8ivtGOmrq+16w=="], + "electron-to-chromium": ["electron-to-chromium@1.5.286", "", {}, "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A=="], + "electron-updater": ["electron-updater@6.8.3", "", { "dependencies": { "builder-util-runtime": "9.5.1", "fs-extra": "^10.1.0", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", "lodash.escaperegexp": "^4.1.2", "lodash.isequal": "^4.5.0", "semver": "~7.7.3", "tiny-typed-emitter": "^2.1.0" } }, "sha512-Z6sgw3jgbikWKXei1ENdqFOxBP0WlXg3TtKfz0rgw2vIZFJUyI4pD7ZN7jrkm7EoMK+tcm/qTnPUdqfZukBlBQ=="], + + "electron-vite": ["electron-vite@5.0.0", "", { "dependencies": { "@babel/core": "^7.28.4", "@babel/plugin-transform-arrow-functions": "^7.27.1", "cac": "^6.7.14", "esbuild": "^0.25.11", "magic-string": "^0.30.19", "picocolors": "^1.1.1" }, "peerDependencies": { "@swc/core": "^1.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["@swc/core"], "bin": { "electron-vite": "bin/electron-vite.js" } }, "sha512-OHp/vjdlubNlhNkPkL/+3JD34ii5ov7M0GpuXEVdQeqdQ3ulvVR7Dg/rNBLfS5XPIFwgoBLDf9sjjrL+CuDyRQ=="], + + "electron-window-state": ["electron-window-state@5.0.3", "", { "dependencies": { "jsonfile": "^4.0.0", "mkdirp": "^0.5.1" } }, "sha512-1mNTwCfkolXl3kMf50yW3vE2lZj0y92P/HYWFBrb+v2S/pCka5mdwN3cagKm458A7NjndSwijynXgcLWRodsVg=="], + + "electron-winstaller": ["electron-winstaller@5.4.0", "", { "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", "fs-extra": "^7.0.1", "lodash": "^4.17.21", "temp": "^0.9.0" }, "optionalDependencies": { "@electron/windows-sign": "^1.1.2" } }, "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg=="], + "emmet": ["emmet@2.4.11", "", { "dependencies": { "@emmetio/abbreviation": "^2.3.3", "@emmetio/css-abbreviation": "^2.1.8" } }, "sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ=="], "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], @@ -2549,6 +2726,10 @@ "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], + "encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="], + + "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], + "engine.io-client": ["engine.io-client@6.6.4", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1", "engine.io-parser": "~5.2.1", "ws": "~8.18.3", "xmlhttprequest-ssl": "~2.1.1" } }, "sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw=="], "engine.io-parser": ["engine.io-parser@5.2.3", "", {}, "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q=="], @@ -2557,6 +2738,10 @@ "entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], + "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], + + "err-code": ["err-code@2.0.3", "", {}, "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="], + "error-stack-parser": ["error-stack-parser@2.1.4", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ=="], "error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="], @@ -2579,6 +2764,8 @@ "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="], + "es6-error": ["es6-error@4.1.1", "", {}, "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="], + "esast-util-from-estree": ["esast-util-from-estree@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "unist-util-position-from-estree": "^2.0.0" } }, "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ=="], "esast-util-from-js": ["esast-util-from-js@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "acorn": "^8.0.0", "esast-util-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw=="], @@ -2631,6 +2818,8 @@ "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="], + "exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="], + "express": ["express@4.22.1", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "~1.20.3", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "~1.3.1", "fresh": "~0.5.2", "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", "serve-static": "~1.16.2", "setprototypeof": "1.2.0", "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g=="], "express-rate-limit": ["express-rate-limit@7.5.1", "", { "peerDependencies": { "express": ">= 4.11" } }, "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw=="], @@ -2643,6 +2832,10 @@ "extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="], + "extract-zip": ["extract-zip@2.0.1", "", { "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" }, "optionalDependencies": { "@types/yauzl": "^2.9.1" }, "bin": { "extract-zip": "cli.js" } }, "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg=="], + + "extsprintf": ["extsprintf@1.4.1", "", {}, "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA=="], + "fast-content-type-parse": ["fast-content-type-parse@3.0.0", "", {}, "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg=="], "fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="], @@ -2653,6 +2846,8 @@ "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + "fast-json-stringify": ["fast-json-stringify@6.3.0", "", { "dependencies": { "@fastify/merge-json-schemas": "^0.2.0", "ajv": "^8.12.0", "ajv-formats": "^3.0.1", "fast-uri": "^3.0.0", "json-schema-ref-resolver": "^3.0.0", "rfdc": "^1.2.0" } }, "sha512-oRCntNDY/329HJPlmdNLIdogNtt6Vyjb1WuT01Soss3slIdyUp8kAcDU3saQTOquEK8KFVfwIIF7FebxUAu+yA=="], "fast-querystring": ["fast-querystring@1.1.2", "", { "dependencies": { "fast-decode-uri-component": "^1.0.1" } }, "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg=="], @@ -2667,12 +2862,16 @@ "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], + "fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="], + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], "file-type": ["file-type@16.5.4", "", { "dependencies": { "readable-web-to-node-stream": "^3.0.0", "strtok3": "^6.2.4", "token-types": "^4.1.1" } }, "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw=="], + "filelist": ["filelist@1.0.6", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA=="], + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], "finalhandler": ["finalhandler@1.3.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "statuses": "~2.0.2", "unpipe": "~1.0.0" } }, "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg=="], @@ -2715,6 +2914,8 @@ "fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], + "fs-minipass": ["fs-minipass@3.0.3", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw=="], + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], @@ -2749,7 +2950,7 @@ "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], - "get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="], + "get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="], @@ -2769,6 +2970,8 @@ "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], + "global-agent": ["global-agent@3.0.0", "", { "dependencies": { "boolean": "^3.0.1", "es6-error": "^4.1.1", "matcher": "^3.0.0", "roarr": "^2.15.3", "semver": "^7.3.2", "serialize-error": "^7.0.1" } }, "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q=="], + "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], "globby": ["globby@11.0.4", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.1.1", "ignore": "^5.1.4", "merge2": "^1.3.0", "slash": "^3.0.0" } }, "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg=="], @@ -2779,6 +2982,8 @@ "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + "got": ["got@11.8.6", "", { "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", "@types/cacheable-request": "^6.0.1", "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", "http2-wrapper": "^1.0.0-beta.5.2", "lowercase-keys": "^2.0.0", "p-cancelable": "^2.0.0", "responselike": "^2.0.0" } }, "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g=="], + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], "graphql": ["graphql@16.12.0", "", {}, "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ=="], @@ -2857,6 +3062,8 @@ "hono-openapi": ["hono-openapi@1.1.2", "", { "peerDependencies": { "@hono/standard-validator": "^0.2.0", "@standard-community/standard-json": "^0.3.5", "@standard-community/standard-openapi": "^0.2.9", "@types/json-schema": "^7.0.15", "hono": "^4.8.3", "openapi-types": "^12.1.3" }, "optionalPeers": ["@hono/standard-validator", "hono"] }, "sha512-toUcO60MftRBxqcVyxsHNYs2m4vf4xkQaiARAucQx3TiBPDtMNNkoh+C4I1vAretQZiGyaLOZNWn1YxfSyUA5g=="], + "hosted-git-info": ["hosted-git-info@4.1.0", "", { "dependencies": { "lru-cache": "^6.0.0" } }, "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA=="], + "html-entities": ["html-entities@2.3.3", "", {}, "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA=="], "html-escaper": ["html-escaper@3.0.3", "", {}, "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="], @@ -2879,6 +3086,8 @@ "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], + "http2-wrapper": ["http2-wrapper@1.0.3", "", { "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" } }, "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg=="], + "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], "human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="], @@ -2889,6 +3098,8 @@ "i18next": ["i18next@23.16.8", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg=="], + "iconv-corefoundation": ["iconv-corefoundation@1.1.7", "", { "dependencies": { "cli-truncate": "^2.1.0", "node-addon-api": "^1.6.3" }, "os": "darwin" }, "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ=="], + "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], "ieee754": ["ieee754@1.1.13", "", {}, "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="], @@ -2901,8 +3112,12 @@ "import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="], + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], + "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], "ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], @@ -2911,6 +3126,8 @@ "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], + "ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="], + "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], "iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="], @@ -2967,6 +3184,8 @@ "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="], + "is-interactive": ["is-interactive@1.0.0", "", {}, "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="], + "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="], @@ -2995,6 +3214,8 @@ "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="], + "is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="], + "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="], "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="], @@ -3011,7 +3232,9 @@ "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + "isbinaryfile": ["isbinaryfile@5.0.7", "", {}, "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ=="], + + "isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="], "isomorphic-ws": ["isomorphic-ws@5.0.0", "", { "peerDependencies": { "ws": "*" } }, "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw=="], @@ -3021,6 +3244,8 @@ "jackspeak": ["jackspeak@4.2.3", "", { "dependencies": { "@isaacs/cliui": "^9.0.0" } }, "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg=="], + "jake": ["jake@10.9.4", "", { "dependencies": { "async": "^3.2.6", "filelist": "^1.0.4", "picocolors": "^1.1.1" }, "bin": { "jake": "bin/cli.js" } }, "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA=="], + "jimp": ["jimp@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/diff": "1.6.0", "@jimp/js-bmp": "1.6.0", "@jimp/js-gif": "1.6.0", "@jimp/js-jpeg": "1.6.0", "@jimp/js-png": "1.6.0", "@jimp/js-tiff": "1.6.0", "@jimp/plugin-blit": "1.6.0", "@jimp/plugin-blur": "1.6.0", "@jimp/plugin-circle": "1.6.0", "@jimp/plugin-color": "1.6.0", "@jimp/plugin-contain": "1.6.0", "@jimp/plugin-cover": "1.6.0", "@jimp/plugin-crop": "1.6.0", "@jimp/plugin-displace": "1.6.0", "@jimp/plugin-dither": "1.6.0", "@jimp/plugin-fisheye": "1.6.0", "@jimp/plugin-flip": "1.6.0", "@jimp/plugin-hash": "1.6.0", "@jimp/plugin-mask": "1.6.0", "@jimp/plugin-print": "1.6.0", "@jimp/plugin-quantize": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/plugin-rotate": "1.6.0", "@jimp/plugin-threshold": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0" } }, "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg=="], "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], @@ -3049,6 +3274,8 @@ "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="], "json-schema-ref-resolver": ["json-schema-ref-resolver@3.0.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A=="], @@ -3059,11 +3286,13 @@ "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="], + "json-stringify-safe": ["json-stringify-safe@5.0.1", "", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="], + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], - "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], + "jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], "jsonwebtoken": ["jsonwebtoken@9.0.3", "", { "dependencies": { "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g=="], @@ -3075,6 +3304,8 @@ "katex": ["katex@0.16.27", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw=="], + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + "kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="], "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], @@ -3085,6 +3316,8 @@ "language-map": ["language-map@1.5.0", "", {}, "sha512-n7gFZpe+DwEAX9cXVTw43i3wiudWDDtSn28RmdnS/HCPr284dQI/SztsamWanRr75oSlKSaGbV2nmWCTzGCoVg=="], + "lazy-val": ["lazy-val@1.0.5", "", {}, "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q=="], + "lazystream": ["lazystream@1.0.1", "", { "dependencies": { "readable-stream": "^2.0.5" } }, "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw=="], "leac": ["leac@0.6.0", "", {}, "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg=="], @@ -3121,10 +3354,14 @@ "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="], + "lodash.escaperegexp": ["lodash.escaperegexp@4.1.2", "", {}, "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw=="], + "lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="], "lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="], + "lodash.isequal": ["lodash.isequal@4.5.0", "", {}, "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="], + "lodash.isinteger": ["lodash.isinteger@4.0.4", "", {}, "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="], "lodash.isnumber": ["lodash.isnumber@3.0.3", "", {}, "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="], @@ -3135,6 +3372,8 @@ "lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="], + "log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="], + "loglevelnext": ["loglevelnext@6.0.0", "", {}, "sha512-FDl1AI2sJGjHHG3XKJd6sG3/6ncgiGCQ0YkW46nxe7SfqQq6hujd9CvFXIXtkGBUN83KPZ2KSOJK8q5P0bSSRQ=="], "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], @@ -3147,6 +3386,8 @@ "lower-case": ["lower-case@2.0.2", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg=="], + "lowercase-keys": ["lowercase-keys@2.0.0", "", {}, "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="], + "lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="], "lru.min": ["lru.min@1.1.4", "", {}, "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA=="], @@ -3161,6 +3402,8 @@ "magicast": ["magicast@0.3.5", "", { "dependencies": { "@babel/parser": "^7.25.4", "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ=="], + "make-fetch-happen": ["make-fetch-happen@14.0.3", "", { "dependencies": { "@npmcli/agent": "^3.0.0", "cacache": "^19.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^5.0.0", "promise-retry": "^2.0.1", "ssri": "^12.0.0" } }, "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ=="], + "markdown-extensions": ["markdown-extensions@2.0.0", "", {}, "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q=="], "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], @@ -3171,6 +3414,8 @@ "marked-shiki": ["marked-shiki@1.2.1", "", { "peerDependencies": { "marked": ">=7.0.0", "shiki": ">=1.0.0" } }, "sha512-yHxYQhPY5oYaIRnROn98foKhuClark7M373/VpLxiy5TrDu9Jd/LsMwo8w+U91Up4oDb9IXFrP0N1MFRz8W/DQ=="], + "matcher": ["matcher@3.0.0", "", { "dependencies": { "escape-string-regexp": "^4.0.0" } }, "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng=="], + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], "md-to-react-email": ["md-to-react-email@5.0.0", "", { "dependencies": { "marked": "7.0.4" }, "peerDependencies": { "react": "18.x" } }, "sha512-GdBrBUbAAJHypnuyofYGfVos8oUslxHx69hs3CW9P0L8mS1sT6GnJuMBTlz/Fw+2widiwdavcu9UwyLF/BzZ4w=="], @@ -3307,6 +3552,10 @@ "mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="], + "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], + + "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], + "min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="], "miniflare": ["miniflare@4.20251118.1", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "7.14.0", "workerd": "1.20251118.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-uLSAE/DvOm392fiaig4LOaatxLjM7xzIniFRG5Y3yF9IduOYLLK/pkCPQNCgKQH3ou0YJRHnTN+09LPfqYNTQQ=="], @@ -3317,12 +3566,28 @@ "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "minipass-collect": ["minipass-collect@2.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw=="], + + "minipass-fetch": ["minipass-fetch@4.0.1", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^3.0.1" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ=="], + + "minipass-flush": ["minipass-flush@1.0.5", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw=="], + + "minipass-pipeline": ["minipass-pipeline@1.2.4", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A=="], + + "minipass-sized": ["minipass-sized@1.0.3", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g=="], + "minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="], "mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="], "morphdom": ["morphdom@2.7.8", "", {}, "sha512-D/fR4xgGUyVRbdMGU6Nejea1RFzYxYtyurG4Fbv2Fi/daKlWKuXGLOdXtl+3eIwL110cI2hz1ZojGICjjFLgTg=="], + "motion": ["motion@12.34.5", "", { "dependencies": { "framer-motion": "^12.34.5", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-N06NLJ9IeBHeielRqIvYvjPfXuRdyTxa+9++BgpGa+hY2D7TcMkI6QzV3jaRuv0aZRXgMa7cPy9YcBUBisPzAQ=="], + + "motion-dom": ["motion-dom@12.34.3", "", { "dependencies": { "motion-utils": "^12.29.2" } }, "sha512-sYgFe+pR9aIM7o4fhs2aXtOI+oqlUd33N9Yoxcgo1Fv7M20sRkHtCmzE/VRNIcq7uNJ+qio+Xubt1FXH3pQ+eQ=="], + + "motion-utils": ["motion-utils@12.29.2", "", {}, "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A=="], + "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], @@ -3359,14 +3624,20 @@ "no-case": ["no-case@3.0.4", "", { "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" } }, "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg=="], + "node-abi": ["node-abi@4.26.0", "", { "dependencies": { "semver": "^7.6.3" } }, "sha512-8QwIZqikRvDIkXS2S93LjzhsSPJuIbfaMETWH+Bx8oOT9Sa9UsUtBFQlc3gBNd1+QINjaTloitXr1W3dQLi9Iw=="], + "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], + "node-api-version": ["node-api-version@0.2.1", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q=="], + "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="], + "node-gyp": ["node-gyp@11.5.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "make-fetch-happen": "^14.0.3", "nopt": "^8.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5", "tar": "^7.4.3", "tinyglobby": "^0.2.12", "which": "^5.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ=="], + "node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="], "node-html-parser": ["node-html-parser@7.0.2", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-DxodLVh7a6JMkYzWyc8nBX9MaF4M0lLFYkJHlWOiu7+9/I6mwNK9u5TbAMC7qfqDJEPX9OIoWA2A9t4C2l1mUQ=="], @@ -3379,6 +3650,8 @@ "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + "normalize-url": ["normalize-url@6.1.0", "", {}, "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A=="], + "npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="], "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], @@ -3431,12 +3704,16 @@ "opentui-spinner": ["opentui-spinner@0.0.6", "", { "dependencies": { "cli-spinners": "^3.3.0" }, "peerDependencies": { "@opentui/core": "^0.1.49", "@opentui/react": "^0.1.49", "@opentui/solid": "^0.1.49", "typescript": "^5" }, "optionalPeers": ["@opentui/react", "@opentui/solid"] }, "sha512-xupLOeVQEAXEvVJCvHkfX6fChDWmJIPHe5jyUrVb8+n4XVTX8mBNhitFfB9v2ZbkC1H2UwPab/ElePHoW37NcA=="], + "ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="], + "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="], "oxc-minify": ["oxc-minify@0.96.0", "", { "optionalDependencies": { "@oxc-minify/binding-android-arm64": "0.96.0", "@oxc-minify/binding-darwin-arm64": "0.96.0", "@oxc-minify/binding-darwin-x64": "0.96.0", "@oxc-minify/binding-freebsd-x64": "0.96.0", "@oxc-minify/binding-linux-arm-gnueabihf": "0.96.0", "@oxc-minify/binding-linux-arm-musleabihf": "0.96.0", "@oxc-minify/binding-linux-arm64-gnu": "0.96.0", "@oxc-minify/binding-linux-arm64-musl": "0.96.0", "@oxc-minify/binding-linux-riscv64-gnu": "0.96.0", "@oxc-minify/binding-linux-s390x-gnu": "0.96.0", "@oxc-minify/binding-linux-x64-gnu": "0.96.0", "@oxc-minify/binding-linux-x64-musl": "0.96.0", "@oxc-minify/binding-wasm32-wasi": "0.96.0", "@oxc-minify/binding-win32-arm64-msvc": "0.96.0", "@oxc-minify/binding-win32-x64-msvc": "0.96.0" } }, "sha512-dXeeGrfPJJ4rMdw+NrqiCRtbzVX2ogq//R0Xns08zql2HjV3Zi2SBJ65saqfDaJzd2bcHqvGWH+M44EQCHPAcA=="], "oxc-transform": ["oxc-transform@0.96.0", "", { "optionalDependencies": { "@oxc-transform/binding-android-arm64": "0.96.0", "@oxc-transform/binding-darwin-arm64": "0.96.0", "@oxc-transform/binding-darwin-x64": "0.96.0", "@oxc-transform/binding-freebsd-x64": "0.96.0", "@oxc-transform/binding-linux-arm-gnueabihf": "0.96.0", "@oxc-transform/binding-linux-arm-musleabihf": "0.96.0", "@oxc-transform/binding-linux-arm64-gnu": "0.96.0", "@oxc-transform/binding-linux-arm64-musl": "0.96.0", "@oxc-transform/binding-linux-riscv64-gnu": "0.96.0", "@oxc-transform/binding-linux-s390x-gnu": "0.96.0", "@oxc-transform/binding-linux-x64-gnu": "0.96.0", "@oxc-transform/binding-linux-x64-musl": "0.96.0", "@oxc-transform/binding-wasm32-wasi": "0.96.0", "@oxc-transform/binding-win32-arm64-msvc": "0.96.0", "@oxc-transform/binding-win32-x64-msvc": "0.96.0" } }, "sha512-dQPNIF+gHpSkmC0+Vg9IktNyhcn28Y8R3eTLyzn52UNymkasLicl3sFAtz7oEVuFmCpgGjaUTKkwk+jW2cHpDQ=="], + "p-cancelable": ["p-cancelable@2.1.1", "", {}, "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg=="], + "p-defer": ["p-defer@3.0.0", "", {}, "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw=="], "p-finally": ["p-finally@1.0.0", "", {}, "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="], @@ -3445,6 +3722,8 @@ "p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + "p-map": ["p-map@7.0.4", "", {}, "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ=="], + "p-queue": ["p-queue@8.1.1", "", { "dependencies": { "eventemitter3": "^5.0.1", "p-timeout": "^6.1.2" } }, "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ=="], "p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="], @@ -3489,6 +3768,8 @@ "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], @@ -3503,10 +3784,14 @@ "pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="], + "pe-library": ["pe-library@0.4.1", "", {}, "sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw=="], + "peberminta": ["peberminta@0.9.0", "", {}, "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ=="], "peek-readable": ["peek-readable@4.1.0", "", {}, "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg=="], + "pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="], + "perfect-debounce": ["perfect-debounce@2.1.0", "", {}, "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g=="], "piccolore": ["piccolore@0.1.3", "", {}, "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw=="], @@ -3541,6 +3826,8 @@ "playwright-core": ["playwright-core@1.57.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ=="], + "plist": ["plist@3.1.0", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ=="], + "pngjs": ["pngjs@7.0.0", "", {}, "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow=="], "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], @@ -3563,6 +3850,8 @@ "postgres": ["postgres@3.4.7", "", {}, "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw=="], + "postject": ["postject@1.0.0-alpha.6", "", { "dependencies": { "commander": "^9.4.0" }, "bin": { "postject": "dist/cli.js" } }, "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A=="], + "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="], "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], @@ -3573,16 +3862,24 @@ "prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="], + "proc-log": ["proc-log@5.0.0", "", {}, "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ=="], + "process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="], "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], "process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="], + "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="], + + "promise-retry": ["promise-retry@2.0.1", "", { "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g=="], + "promise.allsettled": ["promise.allsettled@1.0.7", "", { "dependencies": { "array.prototype.map": "^1.0.5", "call-bind": "^1.0.2", "define-properties": "^1.2.0", "es-abstract": "^1.22.1", "get-intrinsic": "^1.2.1", "iterate-value": "^1.0.2" } }, "sha512-hezvKvQQmsFkOdrZfYxUxkyxl8mgFQeT259Ajj9PXdbg9VzBCWrItOev72JyWxkCD5VSSqAeHmlN3tWx4DlmsA=="], "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], + "proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="], + "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], "proto-list": ["proto-list@1.2.4", "", {}, "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA=="], @@ -3591,6 +3888,8 @@ "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], + "punycode": ["punycode@1.3.2", "", {}, "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="], "qs": ["qs@6.15.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ=="], @@ -3603,6 +3902,8 @@ "quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="], + "quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="], + "radix3": ["radix3@1.1.2", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="], "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], @@ -3631,6 +3932,8 @@ "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], + "read-binary-file-arch": ["read-binary-file-arch@1.0.6", "", { "dependencies": { "debug": "^4.3.4" }, "bin": { "read-binary-file-arch": "cli.js" } }, "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg=="], + "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], "readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], @@ -3705,16 +4008,24 @@ "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + "resedit": ["resedit@1.7.2", "", { "dependencies": { "pe-library": "^0.4.1" } }, "sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA=="], + "reselect": ["reselect@4.1.8", "", {}, "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="], "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], + "resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="], + "resolve-cwd": ["resolve-cwd@3.0.0", "", { "dependencies": { "resolve-from": "^5.0.0" } }, "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg=="], "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + "responselike": ["responselike@2.0.1", "", { "dependencies": { "lowercase-keys": "^2.0.0" } }, "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw=="], + + "restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="], + "restructure": ["restructure@3.0.2", "", {}, "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw=="], "ret": ["ret@0.5.0", "", {}, "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw=="], @@ -3727,7 +4038,7 @@ "retext-stringify": ["retext-stringify@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "nlcst-to-string": "^4.0.0", "unified": "^11.0.0" } }, "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA=="], - "retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], + "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], @@ -3735,6 +4046,8 @@ "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], + "roarr": ["roarr@2.15.4", "", { "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" } }, "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A=="], + "rollup": ["rollup@4.57.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.57.1", "@rollup/rollup-android-arm64": "4.57.1", "@rollup/rollup-darwin-arm64": "4.57.1", "@rollup/rollup-darwin-x64": "4.57.1", "@rollup/rollup-freebsd-arm64": "4.57.1", "@rollup/rollup-freebsd-x64": "4.57.1", "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", "@rollup/rollup-linux-arm-musleabihf": "4.57.1", "@rollup/rollup-linux-arm64-gnu": "4.57.1", "@rollup/rollup-linux-arm64-musl": "4.57.1", "@rollup/rollup-linux-loong64-gnu": "4.57.1", "@rollup/rollup-linux-loong64-musl": "4.57.1", "@rollup/rollup-linux-ppc64-gnu": "4.57.1", "@rollup/rollup-linux-ppc64-musl": "4.57.1", "@rollup/rollup-linux-riscv64-gnu": "4.57.1", "@rollup/rollup-linux-riscv64-musl": "4.57.1", "@rollup/rollup-linux-s390x-gnu": "4.57.1", "@rollup/rollup-linux-x64-gnu": "4.57.1", "@rollup/rollup-linux-x64-musl": "4.57.1", "@rollup/rollup-openbsd-x64": "4.57.1", "@rollup/rollup-openharmony-arm64": "4.57.1", "@rollup/rollup-win32-arm64-msvc": "4.57.1", "@rollup/rollup-win32-ia32-msvc": "4.57.1", "@rollup/rollup-win32-x64-gnu": "4.57.1", "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A=="], "rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="], @@ -3761,6 +4074,8 @@ "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + "sanitize-filename": ["sanitize-filename@1.6.3", "", { "dependencies": { "truncate-utf8-bytes": "^1.0.0" } }, "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg=="], + "sax": ["sax@1.2.1", "", {}, "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA=="], "scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], @@ -3773,10 +4088,14 @@ "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], + "semver-compare": ["semver-compare@1.0.0", "", {}, "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="], + "send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], "seq-queue": ["seq-queue@0.0.5", "", {}, "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="], + "serialize-error": ["serialize-error@7.0.1", "", { "dependencies": { "type-fest": "^0.13.1" } }, "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw=="], + "seroval": ["seroval@1.3.2", "", {}, "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ=="], "seroval-plugins": ["seroval-plugins@1.3.3", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w=="], @@ -3817,6 +4136,8 @@ "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="], + "simple-update-notifier": ["simple-update-notifier@2.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w=="], + "simple-xml-to-json": ["simple-xml-to-json@1.2.3", "", {}, "sha512-kWJDCr9EWtZ+/EYYM5MareWj2cRnZGF93YDNpH4jQiHB+hBIZnfPFSQiVMzZOdk+zXWqTZ/9fTeQNu2DqeiudA=="], "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], @@ -3825,12 +4146,20 @@ "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], + "slice-ansi": ["slice-ansi@3.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ=="], + + "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="], + "smol-toml": ["smol-toml@1.6.0", "", {}, "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw=="], "socket.io-client": ["socket.io-client@4.8.3", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1", "engine.io-client": "~6.6.1", "socket.io-parser": "~4.2.4" } }, "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g=="], "socket.io-parser": ["socket.io-parser@4.2.5", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1" } }, "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ=="], + "socks": ["socks@2.8.7", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="], + + "socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="], + "solid-js": ["solid-js@1.9.10", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.3.0", "seroval-plugins": "~1.3.0" } }, "sha512-Coz956cos/EPDlhs6+jsdTxKuJDPT7B5SVIWgABwROyxjY7Xbr8wkzD68Et+NxnV7DLJ3nJdAC2r9InuV/4Jew=="], "solid-list": ["solid-list@0.3.0", "", { "dependencies": { "@corvu/utils": "~0.4.0" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-t4hx/F/l8Vmq+ib9HtZYl7Z9F1eKxq3eKJTXlvcm7P7yI4Z8O7QSOOEVHb/K6DD7M0RxzVRobK/BS5aSfLRwKg=="], @@ -3863,6 +4192,8 @@ "srvx": ["srvx@0.9.8", "", { "bin": { "srvx": "bin/srvx.mjs" } }, "sha512-RZaxTKJEE/14HYn8COLuUOJAt0U55N9l1Xf6jj+T0GoA01EUH1Xz5JtSUOI+EHn+AEgPCVn7gk6jHJffrr06fQ=="], + "ssri": ["ssri@12.0.0", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ=="], + "sst": ["sst@3.18.10", "", { "dependencies": { "aws-sdk": "2.1692.0", "aws4fetch": "1.0.18", "jose": "5.2.3", "opencontrol": "0.0.6", "openid-client": "5.6.4" }, "optionalDependencies": { "sst-darwin-arm64": "3.18.10", "sst-darwin-x64": "3.18.10", "sst-linux-arm64": "3.18.10", "sst-linux-x64": "3.18.10", "sst-linux-x86": "3.18.10", "sst-win32-arm64": "3.18.10", "sst-win32-x64": "3.18.10", "sst-win32-x86": "3.18.10" }, "bin": { "sst": "bin/sst.mjs" } }, "sha512-SY+ldeJ9K5E9q+DhjXA3e2W3BEOzBwkE3IyLSD71uA3/5nRhUAST31iOWEpW36LbIvSQ9uOVDFcebztoLJ8s7w=="], "sst-darwin-arm64": ["sst-darwin-arm64@3.18.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3MwIpMZhhdZKDqLp9ZQNlwkWix5+q+N0PWstuTomYwgZOxCCe6u9IIsoIszSk+GAJJN/jvGZyLiXKeV4iiQvw=="], @@ -3887,6 +4218,8 @@ "stage-js": ["stage-js@1.0.1", "", {}, "sha512-cz14aPp/wY0s3bkb/B93BPP5ZAEhgBbRmAT3CCDqert8eCAqIpQ0RB2zpK8Ksxf+Pisl5oTzvPHtL4CVzzeHcw=="], + "stat-mode": ["stat-mode@1.0.0", "", {}, "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg=="], + "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="], @@ -3895,7 +4228,7 @@ "stoppable": ["stoppable@1.1.0", "", {}, "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw=="], - "storybook": ["storybook@10.2.10", "", { "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^2.0.1", "@testing-library/jest-dom": "^6.6.3", "@testing-library/user-event": "^14.6.1", "@vitest/expect": "3.2.4", "@vitest/spy": "3.2.4", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0", "open": "^10.2.0", "recast": "^0.23.5", "semver": "^7.7.3", "use-sync-external-store": "^1.5.0", "ws": "^8.18.0" }, "peerDependencies": { "prettier": "^2 || ^3" }, "optionalPeers": ["prettier"], "bin": "./dist/bin/dispatcher.js" }, "sha512-N4U42qKgzMHS7DjqLz5bY4P7rnvJtYkWFCyKspZr3FhPUuy6CWOae3aYC2BjXkHrdug0Jyta6VxFTuB1tYUKhg=="], + "storybook": ["storybook@10.2.13", "", { "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^2.0.1", "@testing-library/jest-dom": "^6.6.3", "@testing-library/user-event": "^14.6.1", "@vitest/expect": "3.2.4", "@vitest/spy": "3.2.4", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0", "open": "^10.2.0", "recast": "^0.23.5", "semver": "^7.7.3", "use-sync-external-store": "^1.5.0", "ws": "^8.18.0" }, "peerDependencies": { "prettier": "^2 || ^3" }, "optionalPeers": ["prettier"], "bin": "./dist/bin/dispatcher.js" }, "sha512-heMfJjOfbHvL+wlCAwFZlSxcakyJ5yQDam6e9k2RRArB1veJhRnsjO6lO1hOXjJYrqxfHA/ldIugbBVlCDqfvQ=="], "storybook-solidjs-vite": ["storybook-solidjs-vite@10.0.9", "", { "dependencies": { "@joshwooding/vite-plugin-react-docgen-typescript": "^0.6.1", "@storybook/builder-vite": "^10.0.0", "@storybook/global": "^5.0.0", "vite-plugin-solid": "^2.11.8" }, "peerDependencies": { "solid-js": "^1.9.0", "storybook": "^0.0.0-0 || ^10.0.0", "typescript": ">= 4.9.x", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["typescript"] }, "sha512-n6MwWCL9mK/qIaUutE9vhGB0X1I1hVnKin2NL+iVC5oXfAiuaABVZlr/1oEeEypsgCdyDOcbEbhJmDWmaqGpPw=="], @@ -3933,12 +4266,18 @@ "strtok3": ["strtok3@6.3.0", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^4.1.0" } }, "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw=="], + "stubborn-fs": ["stubborn-fs@2.0.0", "", { "dependencies": { "stubborn-utils": "^1.0.1" } }, "sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA=="], + + "stubborn-utils": ["stubborn-utils@1.0.2", "", {}, "sha512-zOh9jPYI+xrNOyisSelgym4tolKTJCQd5GBhK0+0xJvcYDcwlOoxF/rnFKQ2KRZknXSG9jWAp66fwP6AxN9STg=="], + "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="], "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="], "sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="], + "sumchecker": ["sumchecker@3.0.1", "", { "dependencies": { "debug": "^4.1.0" } }, "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg=="], + "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=="], @@ -3959,6 +4298,10 @@ "tedious": ["tedious@18.6.2", "", { "dependencies": { "@azure/core-auth": "^1.7.2", "@azure/identity": "^4.2.1", "@azure/keyvault-keys": "^4.4.0", "@js-joda/core": "^5.6.1", "@types/node": ">=18", "bl": "^6.0.11", "iconv-lite": "^0.6.3", "js-md4": "^0.3.2", "native-duplexpair": "^1.0.0", "sprintf-js": "^1.1.3" } }, "sha512-g7jC56o3MzLkE3lHkaFe2ZdOVFBahq5bsB60/M4NYUbocw/MCrS89IOEQUFr+ba6pb8ZHczZ/VqCyYeYq0xBAg=="], + "temp": ["temp@0.9.4", "", { "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" } }, "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA=="], + + "temp-file": ["temp-file@3.4.0", "", { "dependencies": { "async-exit-hook": "^2.0.1", "fs-extra": "^10.0.0" } }, "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg=="], + "terracotta": ["terracotta@1.1.0", "", { "dependencies": { "solid-use": "^0.9.1" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-kfQciWUBUBgYkXu7gh3CK3FAJng/iqZslAaY08C+k1Hdx17aVEpcFFb/WPaysxAfcupNH3y53s/pc53xxZauww=="], "terser": ["terser@5.46.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg=="], @@ -3975,10 +4318,14 @@ "thunky": ["thunky@1.1.0", "", {}, "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="], + "tiny-async-pool": ["tiny-async-pool@1.3.0", "", { "dependencies": { "semver": "^5.5.0" } }, "sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA=="], + "tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="], "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="], + "tiny-typed-emitter": ["tiny-typed-emitter@2.1.0", "", {}, "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA=="], + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], "tinycolor2": ["tinycolor2@1.6.0", "", {}, "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="], @@ -3993,6 +4340,10 @@ "titleize": ["titleize@4.0.0", "", {}, "sha512-ZgUJ1K83rhdu7uh7EHAC2BgY5DzoX8V5rTvoWI4vFysggi6YjLe5gUXABPWAU7VkvGP7P/0YiWq+dcPeYDsf1g=="], + "tmp": ["tmp@0.2.5", "", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="], + + "tmp-promise": ["tmp-promise@3.0.3", "", { "dependencies": { "tmp": "^0.2.0" } }, "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ=="], + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], "toad-cache": ["toad-cache@3.7.0", "", {}, "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw=="], @@ -4007,12 +4358,16 @@ "traverse": ["traverse@0.3.9", "", {}, "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ=="], + "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + "tree-sitter-bash": ["tree-sitter-bash@0.25.0", "", { "dependencies": { "node-addon-api": "^8.2.1", "node-gyp-build": "^4.8.2" }, "peerDependencies": { "tree-sitter": "^0.25.0" }, "optionalPeers": ["tree-sitter"] }, "sha512-gZtlj9+qFS81qKxpLfD6H0UssQ3QBc/F0nKkPsiFDyfQF2YBqYvglFJUzchrPpVhZe9kLZTrJ9n2J6lmka69Vg=="], "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], + "truncate-utf8-bytes": ["truncate-utf8-bytes@1.0.2", "", { "dependencies": { "utf8-byte-length": "^1.0.1" } }, "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ=="], + "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], "ts-dedent": ["ts-dedent@2.2.0", "", {}, "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="], @@ -4067,6 +4422,8 @@ "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="], + "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="], + "ulid": ["ulid@3.0.1", "", { "bin": { "ulid": "dist/cli.js" } }, "sha512-dPJyqPzx8preQhqq24bBG1YNkvigm87K8kVEHCD+ruZg24t6IFEFv00xMWfxcC4djmFtiTLdFuADn4+DOz6R7Q=="], "ultrahtml": ["ultrahtml@1.6.0", "", {}, "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw=="], @@ -4089,6 +4446,10 @@ "unifont": ["unifont@0.5.2", "", { "dependencies": { "css-tree": "^3.0.0", "ofetch": "^1.4.1", "ohash": "^2.0.0" } }, "sha512-LzR4WUqzH9ILFvjLAUU7dK3Lnou/qd5kD+IakBtBK4S15/+x2y9VX+DcWQv6s551R6W+vzwgVS6tFg3XggGBgg=="], + "unique-filename": ["unique-filename@4.0.0", "", { "dependencies": { "unique-slug": "^5.0.0" } }, "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ=="], + + "unique-slug": ["unique-slug@5.0.0", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg=="], + "unist-util-find-after": ["unist-util-find-after@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ=="], "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="], @@ -4125,6 +4486,8 @@ "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + "url": ["url@0.10.3", "", { "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" } }, "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ=="], "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], @@ -4133,6 +4496,8 @@ "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="], + "utf8-byte-length": ["utf8-byte-length@1.0.5", "", {}, "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA=="], + "utif2": ["utif2@4.1.0", "", { "dependencies": { "pako": "^1.0.11" } }, "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w=="], "util": ["util@0.12.5", "", { "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", "which-typed-array": "^1.1.2" } }, "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA=="], @@ -4145,6 +4510,8 @@ "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], + "verror": ["verror@1.10.1", "", { "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg=="], + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], "vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="], @@ -4199,6 +4566,8 @@ "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="], + "wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="], + "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="], "web-streams-polyfill": ["web-streams-polyfill@4.0.0-beta.3", "", {}, "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug=="], @@ -4213,7 +4582,9 @@ "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], - "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + "when-exit": ["when-exit@2.1.5", "", {}, "sha512-VGkKJ564kzt6Ms1dbgPP/yuIoQCrsFAnRbptpC5wOEsDaNsbCB2bnfnaA8i/vRs5tjUSEOtIuvl9/MyVsvQZCg=="], + + "which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="], @@ -4267,6 +4638,8 @@ "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + "yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="], + "yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="], "yocto-spinner": ["yocto-spinner@0.2.3", "", { "dependencies": { "yoctocolors": "^2.1.1" } }, "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ=="], @@ -4537,8 +4910,38 @@ "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], + "@develar/schema-utils/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="], + "@dot/log/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "@electron/asar/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="], + + "@electron/asar/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + + "@electron/asar/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + + "@electron/fuses/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "@electron/fuses/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], + + "@electron/get/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + + "@electron/get/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@electron/notarize/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], + + "@electron/osx-sign/isbinaryfile": ["isbinaryfile@4.0.10", "", {}, "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw=="], + + "@electron/rebuild/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "@electron/rebuild/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=="], + + "@electron/universal/fs-extra": ["fs-extra@11.3.3", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg=="], + + "@electron/universal/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "@electron/windows-sign/fs-extra": ["fs-extra@11.3.3", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg=="], + "@fastify/proxy-addr/ipaddr.js": ["ipaddr.js@2.3.0", "", {}, "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg=="], "@gitlab/gitlab-ai-provider/openai": ["openai@6.22.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-7Yvy17F33Bi9RutWbsaYt5hJEEJ/krRPOrwan+f9aCPuMat1WVsb2VNSII5W1EksKT6fF69TG/xj4XzodK3JZw=="], @@ -4593,6 +4996,8 @@ "@jsx-email/doiuse-email/htmlparser2": ["htmlparser2@9.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.1.0", "entities": "^4.5.0" } }, "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ=="], + "@malept/flatpak-bundler/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], + "@mdx-js/mdx/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], "@modelcontextprotocol/sdk/express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="], @@ -4603,6 +5008,8 @@ "@modelcontextprotocol/sdk/zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="], + "@npmcli/agent/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "@octokit/auth-app/@octokit/request": ["@octokit/request@10.0.7", "", { "dependencies": { "@octokit/endpoint": "^11.0.2", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA=="], "@octokit/auth-app/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], @@ -4667,6 +5074,12 @@ "@opencode-ai/desktop/typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="], + "@opencode-ai/desktop-electron/@actions/artifact": ["@actions/artifact@4.0.0", "", { "dependencies": { "@actions/core": "^1.10.0", "@actions/github": "^6.0.1", "@actions/http-client": "^2.1.0", "@azure/core-http": "^3.0.5", "@azure/storage-blob": "^12.15.0", "@octokit/core": "^5.2.1", "@octokit/plugin-request-log": "^1.0.4", "@octokit/plugin-retry": "^3.0.9", "@octokit/request": "^8.4.1", "@octokit/request-error": "^5.1.1", "@protobuf-ts/plugin": "^2.2.3-alpha.1", "archiver": "^7.0.1", "jwt-decode": "^3.1.2", "unzip-stream": "^0.3.1" } }, "sha512-HCc2jMJRAfviGFAh0FsOR/jNfWhirxl7W6z8zDtttt0GltwxBLdEIjLiweOPFl9WbyJRW1VWnPUSAixJqcWUMQ=="], + + "@opencode-ai/desktop-electron/marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], + + "@opencode-ai/desktop-electron/typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="], + "@opencode-ai/web/@shikijs/transformers": ["@shikijs/transformers@3.20.0", "", { "dependencies": { "@shikijs/core": "3.20.0", "@shikijs/types": "3.20.0" } }, "sha512-PrHHMRr3Q5W1qB/42kJW6laqFyWdhrPF2hNR9qjOm1xcSiAO3hAHo7HaVyHE6pMyevmy3i51O8kuGGXC78uK3g=="], "@opentui/solid/@babel/core": ["@babel/core@7.28.0", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", "@babel/helpers": "^7.27.6", "@babel/parser": "^7.28.0", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.0", "@babel/types": "^7.28.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ=="], @@ -4679,6 +5092,8 @@ "@pierre/diffs/diff": ["diff@8.0.3", "", {}, "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ=="], + "@poppinss/dumper/@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="], + "@poppinss/dumper/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], "@protobuf-ts/plugin/typescript": ["typescript@3.9.10", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q=="], @@ -4719,6 +5134,8 @@ "@solidjs/start/vite": ["vite@7.1.10", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "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-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA=="], + "@storybook/builder-vite/@storybook/csf-plugin": ["@storybook/csf-plugin@10.2.10", "", { "dependencies": { "unplugin": "^2.3.5" }, "peerDependencies": { "esbuild": "*", "rollup": "*", "storybook": "^10.2.10", "vite": "*", "webpack": "*" }, "optionalPeers": ["esbuild", "rollup", "vite", "webpack"] }, "sha512-aFvgaNDAnKMjuyhPK5ialT22pPqMN0XfPBNPeeNVPYztngkdKBa8WFqF/umDd47HxAjebq+vn6uId1xHyOHH3g=="], + "@tailwindcss/oxide/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], @@ -4743,6 +5160,8 @@ "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="], + "@types/plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], + "@types/serve-static/@types/send": ["@types/send@0.17.6", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og=="], "@vitest/expect/@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="], @@ -4769,10 +5188,18 @@ "ai-gateway-provider/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.33", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@ai-sdk/provider-utils": "3.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-2KMcR2xAul3u5dGZD7gONgbIki3Hg7Ey+sFu7gsiJ4U2iRU0GDV3ccNq79dTuAEXPDFcOWCUpW8A8jXc0kxJxQ=="], + "ajv-keywords/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="], + "ansi-align/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=="], "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "app-builder-lib/@electron/get": ["@electron/get@3.1.0", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ=="], + + "app-builder-lib/ci-info": ["ci-info@4.3.1", "", {}, "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA=="], + + "app-builder-lib/minimatch": ["minimatch@10.2.1", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A=="], + "archiver-utils/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], "archiver-utils/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], @@ -4805,14 +5232,46 @@ "buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + "builder-util/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "builder-util-runtime/sax": ["sax@1.4.4", "", {}, "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw=="], + "bun-webgpu/@webgpu/types": ["@webgpu/types@0.1.69", "", {}, "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ=="], "c12/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], + "c12/dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="], + + "cacache/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], + + "cacache/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + + "cli-truncate/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=="], + + "clone-response/mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="], + "compress-commons/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], "condense-newlines/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], + "conf/dot-prop": ["dot-prop@9.0.0", "", { "dependencies": { "type-fest": "^4.18.2" } }, "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ=="], + + "conf/env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="], + + "crc/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], + + "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "defaults/clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="], + + "dir-compare/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + + "dir-compare/p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "dmg-builder/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + + "dmg-license/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="], + "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "dot-prop/type-fest": ["type-fest@3.13.1", "", {}, "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g=="], @@ -4821,6 +5280,18 @@ "editorconfig/minimatch": ["minimatch@9.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w=="], + "electron-builder/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "electron-builder/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=="], + + "electron-publish/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "electron-publish/mime": ["mime@2.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="], + + "electron-winstaller/fs-extra": ["fs-extra@7.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="], + + "encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + "engine.io-client/ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="], "es-get-iterator/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], @@ -4831,6 +5302,8 @@ "estree-util-to-js/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + "execa/get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="], + "execa/is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="], "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], @@ -4843,10 +5316,14 @@ "fetch-blob/web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], + "filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], + "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + "fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], + "gaxios/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], "glob/minimatch": ["minimatch@10.2.1", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A=="], @@ -4857,12 +5334,16 @@ "happy-dom/ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="], + "hosted-git-info/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], + "html-minifier-terser/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], "html-minifier-terser/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "htmlparser2/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + "iconv-corefoundation/node-addon-api": ["node-addon-api@1.7.2", "", {}, "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg=="], + "js-beautify/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], "katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="], @@ -4873,6 +5354,12 @@ "lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + "log-symbols/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "make-fetch-happen/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], + + "matcher/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + "md-to-react-email/marked": ["marked@7.0.4", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ=="], "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], @@ -4885,10 +5372,20 @@ "miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], + "minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "minipass-sized/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "motion/framer-motion": ["framer-motion@12.34.5", "", { "dependencies": { "motion-dom": "^12.34.5", "motion-utils": "^12.29.2", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-Z2dQ+o7BsfpJI3+u0SQUNCrN+ajCKJen1blC4rCHx1Ta2EOHs+xKJegLT2aaD9iSMbU3OoX+WabQXkloUbZmJQ=="], + "mssql/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], "nitro/h3": ["h3@2.0.1-rc.5", "", { "dependencies": { "rou3": "^0.7.9", "srvx": "^0.9.1" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"] }, "sha512-qkohAzCab0nLzXNm78tBjZDvtKMTmtygS8BJLT3VPczAQofdqlFXDPkXdLMJN4r05+xqneG8snZJ0HgkERCZTg=="], + "node-gyp/nopt": ["nopt@8.1.0", "", { "dependencies": { "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A=="], + "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], "nypm/citty": ["citty@0.2.1", "", {}, "sha512-kEV95lFBhQgtogAPlQfJJ0WGVSokvLr/UEoFPiKKOXF7pl98HfUVUD0ejsuTCld/9xH9vogSywZ5KqHzXrZpqg=="], @@ -4915,8 +5412,18 @@ "openid-client/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], + "ora/bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], + + "ora/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "ora/cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], + + "ora/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + "p-retry/retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], + "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], @@ -4927,22 +5434,32 @@ "playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], + "plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], + "postcss-css-variables/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "postcss-load-config/lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], + "postject/commander": ["commander@9.5.0", "", {}, "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="], + "pretty-format/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], + "proper-lockfile/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + "raw-body/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], "readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], "readdir-glob/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], + "restore-cursor/onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], + + "restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + "rimraf/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], "router/path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="], @@ -4955,6 +5472,8 @@ "send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], + "serialize-error/type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="], + "sharp/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], "shiki/@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], @@ -4985,8 +5504,12 @@ "tedious/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + "temp/rimraf": ["rimraf@2.6.3", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA=="], + "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + "tiny-async-pool/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + "token-types/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], "tree-sitter-bash/node-addon-api": ["node-addon-api@8.5.0", "", {}, "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A=="], @@ -5001,6 +5524,8 @@ "unifont/ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="], + "uri-js/punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + "utif2/pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="], "vite-plugin-icons-spritesheet/glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="], @@ -5037,6 +5562,8 @@ "yargs/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="], + "yauzl/buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], + "zod-to-json-schema/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "zod-to-ts/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -5139,6 +5666,26 @@ "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + "@develar/schema-utils/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "@electron/asar/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "@electron/fuses/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], + + "@electron/get/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + + "@electron/notarize/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], + + "@electron/rebuild/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=="], + + "@electron/rebuild/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=="], + + "@electron/universal/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], + + "@electron/universal/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "@electron/windows-sign/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], + "@jsx-email/cli/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.19.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA=="], "@jsx-email/cli/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.19.12", "", { "os": "android", "cpu": "arm" }, "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w=="], @@ -5199,6 +5746,8 @@ "@jsx-email/doiuse-email/htmlparser2/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + "@malept/flatpak-bundler/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], + "@modelcontextprotocol/sdk/express/accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], "@modelcontextprotocol/sdk/express/body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="], @@ -5307,6 +5856,8 @@ "@octokit/rest/@octokit/core/before-after-hook": ["before-after-hook@4.0.0", "", {}, "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ=="], + "@opencode-ai/desktop-electron/@actions/artifact/@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="], + "@opencode-ai/desktop/@actions/artifact/@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="], "@opencode-ai/web/@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], @@ -5355,10 +5906,16 @@ "ai-gateway-provider/@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.20", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ=="], + "ajv-keywords/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "app-builder-lib/@electron/get/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + + "app-builder-lib/@electron/get/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "archiver-utils/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], "archiver-utils/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], @@ -5385,12 +5942,40 @@ "c12/chokidar/readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], + "cacache/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + + "cacache/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "cacache/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=="], + + "cli-truncate/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "cli-truncate/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "crc/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "dir-compare/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "dir-compare/p-limit/yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "dmg-license/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + "editorconfig/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "electron-builder/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=="], + + "electron-builder/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=="], + + "electron-winstaller/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + "esbuild-plugin-copy/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "filelist/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], @@ -5403,10 +5988,16 @@ "js-beautify/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=="], + "lazystream/readable-stream/core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], + "lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], "lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + "motion/framer-motion/motion-dom": ["motion-dom@12.34.5", "", { "dependencies": { "motion-utils": "^12.29.2" } }, "sha512-k33CsnxO2K3gBRMUZT+vPmc4Utlb5menKdG0RyVNLtlqRaaJPRWlE9fXl8NTtfZ5z3G8TDvqSu0MENLqSTaHZA=="], + + "node-gyp/nopt/abbrev": ["abbrev@3.0.1", "", {}, "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg=="], + "opencode/@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.20", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ=="], "opencode/@ai-sdk/openai-compatible/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.20", "", { "dependencies": { "@ai-sdk/provider": "2.0.1", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ=="], @@ -5421,12 +6012,20 @@ "opencontrol/@modelcontextprotocol/sdk/zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="], + "ora/bl/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], + + "ora/bl/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + + "ora/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "pkg-up/find-up/locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], "readable-stream/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], "readdir-glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "restore-cursor/onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], + "rimraf/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], "rimraf/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], @@ -5491,6 +6090,8 @@ "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "temp/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], @@ -5671,6 +6272,18 @@ "@aws-sdk/token-providers/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.3.6", "", { "dependencies": { "strnum": "^2.1.2" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-QNI3sAvSvaOiaMl8FYU4trnEzCwiRr8XMWgAHzlrWpTSj+QaCSvOf1h82OEP1s4hiAXhnbXSyFWCf4ldZzZRVA=="], + "@electron/asar/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "@electron/rebuild/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "@electron/rebuild/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=="], + + "@electron/rebuild/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "@electron/rebuild/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "@electron/universal/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "@jsx-email/cli/tailwindcss/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "@jsx-email/cli/tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], @@ -5741,6 +6354,8 @@ "@octokit/rest/@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], + "@opencode-ai/desktop-electron/@actions/artifact/@actions/http-client/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], + "@opencode-ai/desktop/@actions/artifact/@actions/http-client/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], "@slack/web-api/form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], @@ -5749,6 +6364,8 @@ "ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "app-builder-lib/@electron/get/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + "archiver-utils/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], "archiver-utils/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], @@ -5767,10 +6384,28 @@ "babel-plugin-module-resolver/glob/path-scurry/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "cacache/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + + "cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "cli-truncate/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "dir-compare/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "editorconfig/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "electron-builder/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "electron-builder/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=="], + + "electron-builder/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "electron-builder/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=="], + "filelist/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "gray-matter/js-yaml/argparse/sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], "js-beautify/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], @@ -5801,6 +6436,8 @@ "opencontrol/@modelcontextprotocol/sdk/express/type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="], + "ora/bl/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + "pkg-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=="], "pkg-up/find-up/locate-path/path-exists": ["path-exists@3.0.0", "", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="], @@ -5813,6 +6450,8 @@ "rimraf/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "temp/rimraf/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + "tw-to-css/tailwindcss/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "tw-to-css/tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], @@ -5849,6 +6488,10 @@ "@aws-sdk/token-providers/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.1.2", "", {}, "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ=="], + "@electron/rebuild/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "@electron/rebuild/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "@jsx-email/cli/tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "@solidjs/start/shiki/@shikijs/engine-javascript/oniguruma-to-es/regex": ["regex@5.1.1", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw=="], @@ -5863,6 +6506,16 @@ "babel-plugin-module-resolver/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "cacache/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "cacache/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "cacache/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "electron-builder/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "electron-builder/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "js-beautify/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], "js-beautify/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], @@ -5881,6 +6534,8 @@ "rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "temp/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + "tw-to-css/tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "@aws-sdk/credential-provider-cognito-identity/@aws-sdk/client-cognito-identity/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.1.2", "", {}, "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ=="], @@ -5889,6 +6544,10 @@ "archiver-utils/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "cacache/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "cacache/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "js-beautify/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "js-beautify/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], @@ -5896,5 +6555,7 @@ "rimraf/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "rimraf/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "temp/rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], } } diff --git a/flake.lock b/flake.lock index 9efa1883b1..59eb118fa4 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1770812194, - "narHash": "sha256-OH+lkaIKAvPXR3nITO7iYZwew2nW9Y7Xxq0yfM/UcUU=", + "lastModified": 1772091128, + "narHash": "sha256-TnrYykX8Mf/Ugtkix6V+PjW7miU2yClA6uqWl/v6KWM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8482c7ded03bae7550f3d69884f1e611e3bd19e8", + "rev": "3f0336406035444b4a24b942788334af5f906259", "type": "github" }, "original": { diff --git a/infra/console.ts b/infra/console.ts index de72cb072e..128e069863 100644 --- a/infra/console.ts +++ b/infra/console.ts @@ -118,7 +118,6 @@ const ZEN_LITE_PRICE = new sst.Linkable("ZEN_LITE_PRICE", { price: zenLitePrice.id, }, }) -const ZEN_LITE_LIMITS = new sst.Secret("ZEN_LITE_LIMITS") const zenBlackProduct = new stripe.Product("ZenBlack", { name: "OpenCode Black", @@ -142,7 +141,6 @@ const ZEN_BLACK_PRICE = new sst.Linkable("ZEN_BLACK_PRICE", { plan20: zenBlackPrice20.id, }, }) -const ZEN_BLACK_LIMITS = new sst.Secret("ZEN_BLACK_LIMITS") const ZEN_MODELS = [ new sst.Secret("ZEN_MODELS1"), @@ -215,9 +213,8 @@ new sst.cloudflare.x.SolidStart("Console", { AWS_SES_ACCESS_KEY_ID, AWS_SES_SECRET_ACCESS_KEY, ZEN_BLACK_PRICE, - ZEN_BLACK_LIMITS, ZEN_LITE_PRICE, - ZEN_LITE_LIMITS, + new sst.Secret("ZEN_LIMITS"), new sst.Secret("ZEN_SESSION_SECRET"), ...ZEN_MODELS, ...($dev diff --git a/nix/hashes.json b/nix/hashes.json index eaba0d8f0c..0ef20b235d 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-dZoLhWe4smBsOF7WczMySLXSAB1YRO1vfhiOCL1rBf0=", - "aarch64-linux": "sha256-J7nIz1xuVZEHun5WRZkYRySz29B0A8g5g0RRxnIWTYU=", - "aarch64-darwin": "sha256-R2PuhX+EjUBuLE8MF0G0fcUwNaU+5n6V6uVeK89ulzw=", - "x86_64-darwin": "sha256-Bvzfz9TsTpYriZNLSLgpNcNb+BgtkgpjoWqdOtF2IBg=" + "x86_64-linux": "sha256-jtBYpfiE9g0otqZEtOksW1Nbg+O8CJP9OEOEhsa7sa8=", + "aarch64-linux": "sha256-m+YNZIB7I7EMPyfqkKsvDvmBX9R1szmEKxXpxTNFLH8=", + "aarch64-darwin": "sha256-1gVmtkC1/I8sdHZcaeSFJheySVlpCyKCjf9zbVsVqAQ=", + "x86_64-darwin": "sha256-Tvk5YL6Z0xRul4jopbGme/997iHBylXC0Cq3RnjQb+I=" } } diff --git a/nix/node_modules.nix b/nix/node_modules.nix index e918846c24..6c188c07cf 100644 --- a/nix/node_modules.nix +++ b/nix/node_modules.nix @@ -31,6 +31,7 @@ stdenvNoCC.mkDerivation { ../package.json ../patches ../install # required by desktop build (cli.rs include_str!) + ../.github/TEAM_MEMBERS # required by @opencode-ai/script ] ); }; diff --git a/package.json b/package.json index 3fd9f30667..f2c4dac99f 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts", "dev:desktop": "bun --cwd packages/desktop tauri dev", "dev:web": "bun --cwd packages/app dev", + "dev:storybook": "bun --cwd packages/storybook storybook", "typecheck": "bun turbo typecheck", "prepare": "husky", "random": "echo 'Random script'", @@ -35,7 +36,7 @@ "@tsconfig/bun": "1.0.9", "@cloudflare/workers-types": "4.20251008.0", "@openauthjs/openauth": "0.0.0-20250322224806", - "@pierre/diffs": "1.1.0-beta.13", + "@pierre/diffs": "1.1.0-beta.18", "@solid-primitives/storage": "4.3.3", "@tailwindcss/vite": "4.1.11", "diff": "8.0.2", @@ -98,7 +99,8 @@ "protobufjs", "tree-sitter", "tree-sitter-bash", - "web-tree-sitter" + "web-tree-sitter", + "electron" ], "overrides": { "@types/bun": "catalog:", diff --git a/packages/app/create-effect-simplification-spec.md b/packages/app/create-effect-simplification-spec.md new file mode 100644 index 0000000000..cc101ab059 --- /dev/null +++ b/packages/app/create-effect-simplification-spec.md @@ -0,0 +1,515 @@ +# CreateEffect Simplification Implementation Spec + +Reduce reactive misuse across `packages/app`. + +--- + +## Context + +This work targets `packages/app/src`, which currently has 101 `createEffect` calls across 37 files. + +The biggest clusters are `pages/session.tsx` (19), `pages/layout.tsx` (13), `pages/session/file-tabs.tsx` (6), and several context providers that mirror one store into another. + +Key issues from the audit: + +- Derived state is being written through effects instead of computed directly +- Session and file resets are handled by watch-and-clear effects instead of keyed state boundaries +- User-driven actions are hidden inside reactive effects +- Context layers mirror and hydrate child stores with multiple sync effects +- Several areas repeat the same imperative trigger pattern in multiple effects + +Keep the implementation focused on removing unnecessary effects, not on broad UI redesign. + +## Goals + +- Cut high-churn `createEffect` usage in the hottest files first +- Replace effect-driven derived state with reactive derivation +- Replace reset-on-key effects with keyed ownership boundaries +- Move event-driven work to direct actions and write paths +- Remove mirrored store hydration where a single source of truth can exist +- Leave necessary external sync effects in place, but make them narrower and clearer + +## Non-Goals + +- Do not rewrite unrelated component structure just to reduce the count +- Do not change product behavior, navigation flow, or persisted data shape unless required for a cleaner write boundary +- Do not remove effects that bridge to DOM, editors, polling, or external APIs unless there is a clearly safer equivalent +- Do not attempt a repo-wide cleanup outside `packages/app` + +## Effect Taxonomy And Replacement Rules + +Use these rules during implementation. + +### Prefer `createMemo` + +Use `createMemo` when the target value is pure derived state from other signals or stores. + +Do this when an effect only reads reactive inputs and writes another reactive value that could be computed instead. + +Apply this to: + +- `packages/app/src/pages/session.tsx:141` +- `packages/app/src/pages/layout.tsx:557` +- `packages/app/src/components/terminal.tsx:261` +- `packages/app/src/components/session/session-header.tsx:309` + +Rules: + +- If no external system is touched, do not use `createEffect` +- Derive once, then read the memo where needed +- If normalization is required, prefer normalizing at the write boundary before falling back to a memo + +### Prefer Keyed Remounts + +Use keyed remounts when local UI state should reset because an identity changed. + +Do this with `sessionKey`, `scope()`, or another stable identity instead of watching the key and manually clearing signals. + +Apply this to: + +- `packages/app/src/pages/session.tsx:325` +- `packages/app/src/pages/session.tsx:336` +- `packages/app/src/pages/session.tsx:477` +- `packages/app/src/pages/session.tsx:869` +- `packages/app/src/pages/session.tsx:963` +- `packages/app/src/pages/session/message-timeline.tsx:149` +- `packages/app/src/context/file.tsx:100` + +Rules: + +- If the desired behavior is "new identity, fresh local state," key the owner subtree +- Keep state local to the keyed boundary so teardown and recreation handle the reset naturally + +### Prefer Event Handlers And Actions + +Use direct handlers, store actions, and async command functions when work happens because a user clicked, selected, reloaded, or navigated. + +Do this when an effect is just watching for a flag change, command token, or event-bus signal to trigger imperative logic. + +Apply this to: + +- `packages/app/src/pages/layout.tsx:484` +- `packages/app/src/pages/layout.tsx:652` +- `packages/app/src/pages/layout.tsx:776` +- `packages/app/src/pages/layout.tsx:1489` +- `packages/app/src/pages/layout.tsx:1519` +- `packages/app/src/components/file-tree.tsx:328` +- `packages/app/src/pages/session/terminal-panel.tsx:55` +- `packages/app/src/context/global-sync.tsx:148` +- Duplicated trigger sets in: + - `packages/app/src/pages/session/review-tab.tsx:122` + - `packages/app/src/pages/session/review-tab.tsx:130` + - `packages/app/src/pages/session/review-tab.tsx:138` + - `packages/app/src/pages/session/file-tabs.tsx:367` + - `packages/app/src/pages/session/file-tabs.tsx:378` + - `packages/app/src/pages/session/file-tabs.tsx:389` + - `packages/app/src/pages/session/use-session-hash-scroll.ts:144` + - `packages/app/src/pages/session/use-session-hash-scroll.ts:149` + - `packages/app/src/pages/session/use-session-hash-scroll.ts:167` + +Rules: + +- If the trigger is user intent, call the action at the source of that intent +- If the same imperative work is triggered from multiple places, extract one function and call it directly + +### Prefer `onMount` And `onCleanup` + +Use `onMount` and `onCleanup` for lifecycle-only setup and teardown. + +This is the right fit for subscriptions, one-time wiring, timers, and imperative integration that should not rerun for ordinary reactive changes. + +Use this when: + +- Setup should happen once per owner lifecycle +- Cleanup should always pair with teardown +- The work is not conceptually derived state + +### Keep `createEffect` When It Is A Real Bridge + +Keep `createEffect` when it synchronizes reactive data to an external imperative sink. + +Examples that should remain, though they may be narrowed or split: + +- DOM/editor sync in `packages/app/src/components/prompt-input.tsx:690` +- Scroll sync in `packages/app/src/pages/session.tsx:685` +- Scroll/hash sync in `packages/app/src/pages/session/use-session-hash-scroll.ts:149` +- External sync in: + - `packages/app/src/context/language.tsx:207` + - `packages/app/src/context/settings.tsx:110` + - `packages/app/src/context/sdk.tsx:26` +- Polling in: + - `packages/app/src/components/status-popover.tsx:59` + - `packages/app/src/components/dialog-select-server.tsx:273` + +Rules: + +- Keep the effect single-purpose +- Make dependencies explicit and narrow +- Avoid writing back into the same reactive graph unless absolutely required + +## Implementation Plan + +### Phase 0: Classification Pass + +Before changing code, tag each targeted effect as one of: derive, reset, event, lifecycle, or external bridge. + +Acceptance criteria: + +- Every targeted effect in this spec is tagged with a replacement strategy before refactoring starts +- Shared helpers to be introduced are identified up front to avoid repeating patterns + +### Phase 1: Derived-State Cleanup + +Tackle highest-value, lowest-risk derived-state cleanup first. + +Priority items: + +- Normalize tabs at write boundaries and remove `packages/app/src/pages/session.tsx:141` +- Stop syncing `workspaceOrder` in `packages/app/src/pages/layout.tsx:557` +- Make prompt slash filtering reactive so `packages/app/src/components/prompt-input.tsx:652` can be removed +- Replace other obvious derived-state effects in terminal and session header + +Acceptance criteria: + +- No behavior change in tab ordering, prompt filtering, terminal display, or header state +- Targeted derived-state effects are deleted, not just moved + +### Phase 2: Keyed Reset Cleanup + +Replace reset-on-key effects with keyed ownership boundaries. + +Priority items: + +- Key session-scoped UI and state by `sessionKey` +- Key file-scoped state by `scope()` +- Remove manual clear-and-reseed effects in session and file context + +Acceptance criteria: + +- Switching session or file scope recreates the intended local state cleanly +- No stale state leaks across session or scope changes +- Target reset effects are deleted + +### Phase 3: Event-Driven Work Extraction + +Move event-driven work out of reactive effects. + +Priority items: + +- Replace `globalStore.reload` effect dispatching with direct calls +- Split mixed-responsibility effect in `packages/app/src/pages/layout.tsx:1489` +- Collapse duplicated imperative trigger triplets into single functions +- Move file-tree and terminal-panel imperative work to explicit handlers + +Acceptance criteria: + +- User-triggered behavior still fires exactly once per intended action +- No effect remains whose only job is to notice a command-like state and trigger an imperative function + +### Phase 4: Context Ownership Cleanup + +Remove mirrored child-store hydration patterns. + +Priority items: + +- Remove child-store hydration mirrors in `packages/app/src/context/global-sync/child-store.ts:184`, `:190`, `:193` +- Simplify mirror logic in `packages/app/src/context/global-sync.tsx:130`, `:138` +- Revisit `packages/app/src/context/layout.tsx:424` if it still mirrors instead of deriving + +Acceptance criteria: + +- There is one clear source of truth for each synced value +- Child stores no longer need effect-based hydration to stay consistent +- Initialization and updates both work without manual mirror effects + +### Phase 5: Cleanup And Keeper Review + +Clean up remaining targeted hotspots and narrow the effects that should stay. + +Acceptance criteria: + +- Remaining `createEffect` calls in touched files are all true bridges or clearly justified lifecycle sync +- Mixed-responsibility effects are split into smaller units where still needed + +## Detailed Work Items By Area + +### 1. Normalize Tab State + +Files: + +- `packages/app/src/pages/session.tsx:141` + +Work: + +- Move tab normalization into the functions that create, load, or update tab state +- Make readers consume already-normalized tab data +- Remove the effect that rewrites derived tab state after the fact + +Rationale: + +- Tabs should become valid when written, not be repaired later +- This removes a feedback loop and makes state easier to trust + +Acceptance criteria: + +- The effect at `packages/app/src/pages/session.tsx:141` is removed +- Newly created and restored tabs are normalized before they enter local state +- Tab rendering still matches current behavior for valid and edge-case inputs + +### 2. Key Session-Owned State + +Files: + +- `packages/app/src/pages/session.tsx:325` +- `packages/app/src/pages/session.tsx:336` +- `packages/app/src/pages/session.tsx:477` +- `packages/app/src/pages/session.tsx:869` +- `packages/app/src/pages/session.tsx:963` +- `packages/app/src/pages/session/message-timeline.tsx:149` + +Work: + +- Identify state that should reset when `sessionKey` changes +- Move that state under a keyed subtree or keyed owner boundary +- Remove effects that watch `sessionKey` just to clear local state, refs, or temporary UI flags + +Rationale: + +- Session identity already defines the lifetime of this UI state +- Keyed ownership makes reset behavior automatic and easier to reason about + +Acceptance criteria: + +- The targeted reset effects are removed +- Changing sessions resets only the intended session-local state +- Scroll and editor state that should persist are not accidentally reset + +### 3. Derive Workspace Order + +Files: + +- `packages/app/src/pages/layout.tsx:557` + +Work: + +- Stop writing `workspaceOrder` from live workspace data in an effect +- Represent user overrides separately from live workspace data +- Compute effective order from current data plus overrides with a memo or pure helper + +Rationale: + +- Persisted user intent and live source data should not mirror each other through an effect +- A computed effective order avoids drift and racey resync behavior + +Acceptance criteria: + +- The effect at `packages/app/src/pages/layout.tsx:557` is removed +- Workspace order updates correctly when workspaces appear, disappear, or are reordered by the user +- User overrides persist without requiring a sync-back effect + +### 4. Remove Child-Store Mirrors + +Files: + +- `packages/app/src/context/global-sync.tsx:130` +- `packages/app/src/context/global-sync.tsx:138` +- `packages/app/src/context/global-sync.tsx:148` +- `packages/app/src/context/global-sync/child-store.ts:184` +- `packages/app/src/context/global-sync/child-store.ts:190` +- `packages/app/src/context/global-sync/child-store.ts:193` +- `packages/app/src/context/layout.tsx:424` + +Work: + +- Trace the actual ownership of global and child store values +- Replace hydration and mirror effects with explicit initialization and direct updates +- Remove the `globalStore.reload` event-bus pattern and call the needed reload paths directly + +Rationale: + +- Mirrors make it hard to tell which state is authoritative +- Event-bus style state toggles hide control flow and create accidental reruns + +Acceptance criteria: + +- Child store hydration no longer depends on effect-based copying +- Reload work can be followed from the event source to the handler without a reactive relay +- State remains correct on first load, child creation, and subsequent updates + +### 5. Key File-Scoped State + +Files: + +- `packages/app/src/context/file.tsx:100` + +Work: + +- Move file-scoped local state under a boundary keyed by `scope()` +- Remove any effect that watches `scope()` only to reset file-local state + +Rationale: + +- File scope changes are identity changes +- Keyed ownership gives a cleaner reset than manual clear logic + +Acceptance criteria: + +- The effect at `packages/app/src/context/file.tsx:100` is removed +- Switching scopes resets only scope-local state +- No previous-scope data appears after a scope change + +### 6. Split Layout Side Effects + +Files: + +- `packages/app/src/pages/layout.tsx:1489` +- Related event-driven effects near `packages/app/src/pages/layout.tsx:484`, `:652`, `:776`, `:1519` + +Work: + +- Break the mixed-responsibility effect at `:1489` into direct actions and smaller bridge effects only where required +- Move user-triggered branches into the actual command or handler that causes them +- Remove any branch that only exists because one effect is handling unrelated concerns + +Rationale: + +- Mixed effects hide cause and make reruns hard to predict +- Smaller units reduce accidental coupling and make future cleanup safer + +Acceptance criteria: + +- The effect at `packages/app/src/pages/layout.tsx:1489` no longer mixes unrelated responsibilities +- Event-driven branches execute from direct handlers +- Remaining effects in this area each have one clear external sync purpose + +### 7. Remove Duplicate Triggers + +Files: + +- `packages/app/src/pages/session/review-tab.tsx:122` +- `packages/app/src/pages/session/review-tab.tsx:130` +- `packages/app/src/pages/session/review-tab.tsx:138` +- `packages/app/src/pages/session/file-tabs.tsx:367` +- `packages/app/src/pages/session/file-tabs.tsx:378` +- `packages/app/src/pages/session/file-tabs.tsx:389` +- `packages/app/src/pages/session/use-session-hash-scroll.ts:144` +- `packages/app/src/pages/session/use-session-hash-scroll.ts:149` +- `packages/app/src/pages/session/use-session-hash-scroll.ts:167` + +Work: + +- Extract one explicit imperative function per behavior +- Call that function from each source event instead of replicating the same effect pattern multiple times +- Preserve the scroll-sync effect that is truly syncing with the DOM, but remove duplicate trigger scaffolding around it + +Rationale: + +- Duplicate triggers make it easy to miss a case or fire twice +- One named action is easier to test and reason about + +Acceptance criteria: + +- Repeated imperative effect triplets are collapsed into shared functions +- Scroll behavior still works, including hash-based navigation +- No duplicate firing is introduced + +### 8. Make Prompt Filtering Reactive + +Files: + +- `packages/app/src/components/prompt-input.tsx:652` +- Keep `packages/app/src/components/prompt-input.tsx:690` as needed + +Work: + +- Convert slash filtering into a pure reactive derivation from the current input and candidate command list +- Keep only the editor or DOM bridge effect if it is still needed for imperative syncing + +Rationale: + +- Filtering is classic derived state +- It should not need an effect if it can be computed from current inputs + +Acceptance criteria: + +- The effect at `packages/app/src/components/prompt-input.tsx:652` is removed +- Filtered slash-command results update correctly as the input changes +- The editor sync effect at `:690` still behaves correctly + +### 9. Clean Up Smaller Derived-State Cases + +Files: + +- `packages/app/src/components/terminal.tsx:261` +- `packages/app/src/components/session/session-header.tsx:309` + +Work: + +- Replace effect-written local state with memos or inline derivation +- Remove intermediate setters when the value can be computed directly + +Rationale: + +- These are low-risk wins that reinforce the same pattern +- They also help keep follow-up cleanup consistent + +Acceptance criteria: + +- Targeted effects are removed +- UI output remains unchanged under the same inputs + +## Verification And Regression Checks + +Run focused checks after each phase, not only at the end. + +### Suggested Verification + +- Switch between sessions rapidly and confirm local session UI resets only where intended +- Open, close, and reorder tabs and confirm order and normalization remain stable +- Change workspaces, reload workspace data, and verify effective ordering is correct +- Change file scope and confirm stale file state does not bleed across scopes +- Trigger layout actions that previously depended on effects and confirm they still fire once +- Use slash commands in the prompt and verify filtering updates as you type +- Test review tab, file tab, and hash-scroll flows for duplicate or missing triggers +- Verify global sync initialization, reload, and child-store creation paths + +### Regression Checks + +- No accidental infinite reruns +- No double-firing network or command actions +- No lost cleanup for listeners, timers, or scroll handlers +- No preserved stale state after identity changes +- No removed effect that was actually bridging to DOM or an external API + +If available, add or update tests around pure helpers introduced during this cleanup. + +Favor tests for derived ordering, normalization, and action extraction, since those are easiest to lock down. + +## Definition Of Done + +This work is done when all of the following are true: + +- The highest-leverage targets in this spec are implemented +- Each removed effect has been replaced by a clearer pattern: memo, keyed boundary, direct action, or lifecycle hook +- The "should remain" effects still exist only where they serve a real external sync purpose +- Touched files have fewer mixed-responsibility effects and clearer ownership of state +- Manual verification covers session switching, file scope changes, workspace ordering, prompt filtering, and reload flows +- No behavior regressions are found in the targeted areas + +A reduced raw `createEffect` count is helpful, but it is not the main success metric. + +The main success metric is clearer ownership and fewer effect-driven state repairs. + +## Risks And Rollout Notes + +Main risks: + +- Keyed remounts can reset too much if state boundaries are drawn too high +- Store mirror removal can break initialization order if ownership is not mapped first +- Moving event work out of effects can accidentally skip triggers that were previously implicit + +Rollout notes: + +- Land in small phases, with each phase keeping the app behaviorally stable +- Prefer isolated PRs by phase or by file cluster, especially for context-store changes +- Review each remaining effect in touched files and leave it only if it clearly bridges to something external diff --git a/packages/app/e2e/projects/projects-switch.spec.ts b/packages/app/e2e/projects/projects-switch.spec.ts index 74b3890888..81cca6988d 100644 --- a/packages/app/e2e/projects/projects-switch.spec.ts +++ b/packages/app/e2e/projects/projects-switch.spec.ts @@ -92,14 +92,19 @@ test("switching back to a project opens the latest workspace session", async ({ await expect(page).toHaveURL(new RegExp(`/${workspaceSlug}/session(?:[/?#]|$)`)) - const created = await createSdk(workspaceDir) - .session.create() - .then((x) => x.data?.id) - if (!created) throw new Error(`Failed to create session for workspace: ${workspaceDir}`) + // Create a session by sending a prompt + const prompt = page.locator(promptSelector) + await expect(prompt).toBeVisible() + await prompt.fill("test") + await page.keyboard.press("Enter") + + // Wait for the URL to update with the new session ID + await expect.poll(() => sessionIDFromUrl(page.url()) ?? "", { timeout: 15_000 }).not.toBe("") + + const created = sessionIDFromUrl(page.url()) + if (!created) throw new Error(`Failed to get session ID from url: ${page.url()}`) sessionID = created - await page.goto(sessionPath(workspaceDir, created)) - await expect(page.locator(promptSelector)).toBeVisible() await expect(page).toHaveURL(new RegExp(`/${workspaceSlug}/session/${created}(?:[/?#]|$)`)) await openSidebar(page) diff --git a/packages/app/e2e/session/session-composer-dock.spec.ts b/packages/app/e2e/session/session-composer-dock.spec.ts index deb87a0620..4cf075fc9a 100644 --- a/packages/app/e2e/session/session-composer-dock.spec.ts +++ b/packages/app/e2e/session/session-composer-dock.spec.ts @@ -142,6 +142,17 @@ test("default dock shows prompt input", async ({ page, sdk, gotoSession }) => { }) }) +test("auto-accept toggle works before first submit", async ({ page, gotoSession }) => { + await gotoSession() + + const button = page.locator('[data-action="prompt-permissions"]').first() + await expect(button).toBeVisible() + await expect(button).toHaveAttribute("aria-pressed", "false") + + await setAutoAccept(page, true) + await setAutoAccept(page, false) +}) + test("blocked question flow unblocks after submit", async ({ page, sdk, gotoSession }) => { await withDockSession(sdk, "e2e composer dock question", async (session) => { await withDockSeed(sdk, session.id, async () => { diff --git a/packages/app/package.json b/packages/app/package.json index 446c14e967..6f5fdeb2fb 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "1.2.15", + "version": "1.2.16", "description": "", "type": "module", "exports": { diff --git a/packages/app/script/e2e-local.ts b/packages/app/script/e2e-local.ts index 112e2bc60a..9a83411b1d 100644 --- a/packages/app/script/e2e-local.ts +++ b/packages/app/script/e2e-local.ts @@ -145,6 +145,7 @@ try { Object.assign(process.env, serverEnv) process.env.AGENT = "1" process.env.OPENCODE = "1" + process.env.OPENCODE_PID = String(process.pid) const log = await import("../../opencode/src/util/log") const install = await import("../../opencode/src/installation") diff --git a/packages/app/src/app.tsx b/packages/app/src/app.tsx index 4a25e8d948..52a1dac6a2 100644 --- a/packages/app/src/app.tsx +++ b/packages/app/src/app.tsx @@ -7,8 +7,8 @@ import { MarkedProvider } from "@opencode-ai/ui/context/marked" import { Font } from "@opencode-ai/ui/font" import { ThemeProvider } from "@opencode-ai/ui/theme" import { MetaProvider } from "@solidjs/meta" -import { Navigate, Route, Router } from "@solidjs/router" -import { ErrorBoundary, type JSX, lazy, type ParentProps, Show, Suspense } from "solid-js" +import { BaseRouterProps, Navigate, Route, Router } from "@solidjs/router" +import { Component, ErrorBoundary, type JSX, lazy, type ParentProps, Show, Suspense } from "solid-js" import { CommandProvider } from "@/context/command" import { CommentsProvider } from "@/context/comments" import { FileProvider } from "@/context/file" @@ -28,6 +28,7 @@ import { TerminalProvider } from "@/context/terminal" import DirectoryLayout from "@/pages/directory-layout" import Layout from "@/pages/layout" import { ErrorPage } from "./pages/error" +import { Dynamic } from "solid-js/web" const Home = lazy(() => import("@/pages/home")) const Session = lazy(() => import("@/pages/session")) @@ -144,13 +145,15 @@ export function AppInterface(props: { children?: JSX.Element defaultServer: ServerConnection.Key servers?: Array + router?: Component }) { return ( - {routerProps.children}} > @@ -158,7 +161,7 @@ export function AppInterface(props: { - + diff --git a/packages/app/src/components/dialog-connect-provider.tsx b/packages/app/src/components/dialog-connect-provider.tsx index 90f4f41f7c..b042205cf4 100644 --- a/packages/app/src/components/dialog-connect-provider.tsx +++ b/packages/app/src/components/dialog-connect-provider.tsx @@ -4,7 +4,6 @@ import { useDialog } from "@opencode-ai/ui/context/dialog" import { Dialog } from "@opencode-ai/ui/dialog" import { Icon } from "@opencode-ai/ui/icon" import { IconButton } from "@opencode-ai/ui/icon-button" -import type { IconName } from "@opencode-ai/ui/icons/provider" import { List, type ListRef } from "@opencode-ai/ui/list" import { ProviderIcon } from "@opencode-ai/ui/provider-icon" import { Spinner } from "@opencode-ai/ui/spinner" @@ -447,7 +446,7 @@ export function DialogConnectProvider(props: { provider: string }) { >
- +
diff --git a/packages/app/src/components/dialog-select-model-unpaid.tsx b/packages/app/src/components/dialog-select-model-unpaid.tsx index 5ca29a520a..bcee3f501f 100644 --- a/packages/app/src/components/dialog-select-model-unpaid.tsx +++ b/packages/app/src/components/dialog-select-model-unpaid.tsx @@ -1,7 +1,6 @@ import { Button } from "@opencode-ai/ui/button" import { useDialog } from "@opencode-ai/ui/context/dialog" import { Dialog } from "@opencode-ai/ui/dialog" -import type { IconName } from "@opencode-ai/ui/icons/provider" import { List, type ListRef } from "@opencode-ai/ui/list" import { ProviderIcon } from "@opencode-ai/ui/provider-icon" import { Tag } from "@opencode-ai/ui/tag" @@ -95,7 +94,7 @@ export const DialogSelectModelUnpaid: Component = () => { > {(i) => (
- + {i.name}
{language.t("dialog.provider.opencode.tagline")}
diff --git a/packages/app/src/components/dialog-select-provider.tsx b/packages/app/src/components/dialog-select-provider.tsx index 76e718bb00..e53738399a 100644 --- a/packages/app/src/components/dialog-select-provider.tsx +++ b/packages/app/src/components/dialog-select-provider.tsx @@ -5,18 +5,12 @@ import { Dialog } from "@opencode-ai/ui/dialog" import { List } from "@opencode-ai/ui/list" import { Tag } from "@opencode-ai/ui/tag" import { ProviderIcon } from "@opencode-ai/ui/provider-icon" -import { iconNames, type IconName } from "@opencode-ai/ui/icons/provider" import { DialogConnectProvider } from "./dialog-connect-provider" import { useLanguage } from "@/context/language" import { DialogCustomProvider } from "./dialog-custom-provider" const CUSTOM_ID = "_custom" -function icon(id: string): IconName { - if (iconNames.includes(id as IconName)) return id as IconName - return "synthetic" -} - export const DialogSelectProvider: Component = () => { const dialog = useDialog() const providers = useProviders() @@ -69,7 +63,7 @@ export const DialogSelectProvider: Component = () => { > {(i) => (
- + {i.name}
{language.t("dialog.provider.opencode.tagline")}
diff --git a/packages/app/src/components/file-tree.tsx b/packages/app/src/components/file-tree.tsx index 3840f18ed8..930832fb65 100644 --- a/packages/app/src/components/file-tree.tsx +++ b/packages/app/src/components/file-tree.tsx @@ -325,12 +325,6 @@ export default function FileTree(props: { ), ) - createEffect(() => { - const dir = file.tree.state(props.path) - if (!shouldListExpanded({ level, dir })) return - void file.tree.list(props.path) - }) - const nodes = createMemo(() => { const nodes = file.tree.children(props.path) const current = filter() diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 3ba3763b8c..c9c8bc6b44 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -1,4 +1,5 @@ import { useFilteredList } from "@opencode-ai/ui/hooks" +import { useSpring } from "@opencode-ai/ui/motion-spring" import { createEffect, on, Component, Show, onCleanup, Switch, Match, createMemo, createSignal } from "solid-js" import { createStore } from "solid-js/store" import { createFocusSignal } from "@solid-primitives/active-element" @@ -23,7 +24,6 @@ import { Button } from "@opencode-ai/ui/button" import { DockShellForm, DockTray } from "@opencode-ai/ui/dock-surface" import { Icon } from "@opencode-ai/ui/icon" import { ProviderIcon } from "@opencode-ai/ui/provider-icon" -import type { IconName } from "@opencode-ai/ui/icons/provider" import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip" import { IconButton } from "@opencode-ai/ui/icon-button" import { Select } from "@opencode-ai/ui/select" @@ -244,6 +244,7 @@ export const PromptInput: Component = (props) => { draggingType: "image" | "@mention" | null mode: "normal" | "shell" applyingHistory: boolean + pendingAutoAccept: boolean }>({ popover: null, historyIndex: -1, @@ -252,8 +253,11 @@ export const PromptInput: Component = (props) => { draggingType: null, mode: "normal", applyingHistory: false, + pendingAutoAccept: false, }) + const buttonsSpring = useSpring(() => (store.mode === "normal" ? 1 : 0), { visualDuration: 0.2, bounce: 0 }) + const commentCount = createMemo(() => { if (store.mode === "shell") return 0 return prompt.context.items().filter((item) => !!item.comment?.trim()).length @@ -302,6 +306,12 @@ export const PromptInput: Component = (props) => { }), ) + createEffect( + on(sessionKey, () => { + setStore("pendingAutoAccept", false) + }), + ) + const historyComments = () => { const byID = new Map(comments.all().map((item) => [`${item.file}\n${item.id}`, item] as const)) return prompt.context.items().flatMap((item) => { @@ -592,7 +602,6 @@ export const PromptInput: Component = (props) => { setActive: setSlashActive, onInput: slashOnInput, onKeyDown: slashOnKeyDown, - refetch: slashRefetch, } = useFilteredList({ items: slashCommands, key: (x) => x?.id, @@ -649,14 +658,6 @@ export const PromptInput: Component = (props) => { } } - createEffect( - on( - () => sync.data.command, - () => slashRefetch(), - { defer: true }, - ), - ) - // Auto-scroll active command into view when navigating with keyboard createEffect(() => { const activeId = slashActive() @@ -957,10 +958,18 @@ export const PromptInput: Component = (props) => { readClipboardImage: platform.readClipboardImage, }) + const variants = createMemo(() => ["default", ...local.model.variant.list()]) + const accepting = createMemo(() => { + const id = params.id + if (!id) return store.pendingAutoAccept + return permission.isAutoAccepting(id, sdk.directory) + }) + const { abort, handleSubmit } = createPromptSubmit({ info, imageAttachments, commentCount, + autoAccept: () => accepting(), mode: () => store.mode, working, editor: () => editorRef, @@ -1125,13 +1134,6 @@ export const PromptInput: Component = (props) => { } } - const variants = createMemo(() => ["default", ...local.model.variant.list()]) - const accepting = createMemo(() => { - const id = params.id - if (!id) return false - return permission.isAutoAccepting(id, sdk.directory) - }) - return (
= (props) => {
0.5 ? "auto" : "none", }} > = (props) => { type="button" variant="ghost" class="size-8 p-0" + style={{ + opacity: buttonsSpring(), + transform: `scale(${0.95 + buttonsSpring() * 0.05})`, + filter: `blur(${(1 - buttonsSpring()) * 2}px)`, + }} onClick={pick} disabled={store.mode !== "normal"} tabIndex={store.mode === "normal" ? undefined : -1} @@ -1304,6 +1310,11 @@ export const PromptInput: Component = (props) => { icon={working() ? "stop" : "arrow-up"} variant="primary" class="size-8" + style={{ + opacity: buttonsSpring(), + transform: `scale(${0.95 + buttonsSpring() * 0.05})`, + filter: `blur(${(1 - buttonsSpring()) * 2}px)`, + }} aria-label={working() ? language.t("prompt.action.stop") : language.t("prompt.action.send")} /> @@ -1323,9 +1334,11 @@ export const PromptInput: Component = (props) => { -
- - + 0 || props.historyMore}>
- - {(message) => { - const comments = createMemo(() => messageComments(sync.data.part[message.id] ?? [])) + + {(messageID) => { + const active = createMemo(() => activeMessageID() === messageID) + const queued = createMemo(() => { + if (active()) return false + const activeID = activeMessageID() + if (activeID) return messageID > activeID + return false + }) + const comments = createMemo(() => messageComments(sync.data.part[messageID] ?? []), [], { + equals: (a, b) => JSON.stringify(a) === JSON.stringify(b), + }) + const commentCount = createMemo(() => comments().length) return (
{ - props.onRegisterMessage(el, message.id) - onCleanup(() => props.onUnregisterMessage(message.id)) + props.onRegisterMessage(el, messageID) + onCleanup(() => props.onUnregisterMessage(messageID)) }} classList={{ "min-w-0 w-full max-w-full": true, "md:max-w-200 2xl:max-w-[1000px]": props.centered, }} > - 0}> + 0}>
- - {(comment) => ( -
-
- - {getFilename(comment.path)} - - {(selection) => ( - - {selection().startLine === selection().endLine - ? `:${selection().startLine}` - : `:${selection().startLine}-${selection().endLine}`} - - )} - + + {(commentAccessor: () => MessageComment) => { + const comment = createMemo(() => commentAccessor()) + return ( +
+
+ + {getFilename(comment().path)} + + {(selection) => ( + + {selection().startLine === selection().endLine + ? `:${selection().startLine}` + : `:${selection().startLine}-${selection().endLine}`} + + )} + +
+
+ {comment().comment} +
-
- {comment.comment} -
-
- )} - + ) + }} +
props.diffs().length, - () => queueRestore(), - { defer: true }, - ), - ) - - createEffect( - on( - () => props.diffStyle, - () => queueRestore(), - { defer: true }, - ), - ) - - createEffect( - on( - () => layout.ready(), - (ready) => { - if (!ready) return - queueRestore() - }, - { defer: true }, - ), - ) + createEffect(() => { + props.diffs().length + props.diffStyle + if (!layout.ready()) return + queueRestore() + }) onCleanup(() => { if (restoreFrame !== undefined) cancelAnimationFrame(restoreFrame) @@ -176,7 +156,7 @@ export function SessionReviewTab(props: SessionReviewTabProps) { open={props.view().review.open()} onOpenChange={props.view().review.setOpen} classes={{ - root: props.classes?.root ?? "pb-6 pr-3", + root: props.classes?.root ?? "pr-3", header: props.classes?.header ?? "px-3", container: props.classes?.container ?? "pl-3", }} diff --git a/packages/app/src/pages/session/terminal-panel.tsx b/packages/app/src/pages/session/terminal-panel.tsx index 27ea4e6f31..49bed94906 100644 --- a/packages/app/src/pages/session/terminal-panel.tsx +++ b/packages/app/src/pages/session/terminal-panel.tsx @@ -56,9 +56,9 @@ export function TerminalPanel() { on( () => terminal.all().length, (count, prevCount) => { - if (prevCount !== undefined && prevCount > 0 && count === 0) { - if (opened()) view().terminal.toggle() - } + if (prevCount === undefined || prevCount <= 0 || count !== 0) return + if (!opened()) return + close() }, ), ) diff --git a/packages/app/src/pages/session/use-session-hash-scroll.ts b/packages/app/src/pages/session/use-session-hash-scroll.ts index b704e460bc..473409fd99 100644 --- a/packages/app/src/pages/session/use-session-hash-scroll.ts +++ b/packages/app/src/pages/session/use-session-hash-scroll.ts @@ -1,4 +1,4 @@ -import { createEffect, createMemo, on, onCleanup } from "solid-js" +import { createEffect, createMemo, onCleanup, onMount } from "solid-js" import { UserMessage } from "@opencode-ai/sdk/v2" export const messageIdFromHash = (hash: string) => { @@ -19,7 +19,6 @@ export const useSessionHashScroll = (input: { setPendingMessage: (value: string | undefined) => void setActiveMessage: (message: UserMessage | undefined) => void setTurnStart: (value: number) => void - scheduleTurnBackfill: () => void autoScroll: { pause: () => void; forceScrollToBottom: () => void } scroller: () => HTMLDivElement | undefined anchor: (id: string) => string @@ -29,6 +28,7 @@ export const useSessionHashScroll = (input: { const visibleUserMessages = createMemo(() => input.visibleUserMessages()) const messageById = createMemo(() => new Map(visibleUserMessages().map((m) => [m.id, m]))) const messageIndex = createMemo(() => new Map(visibleUserMessages().map((m, i) => [m.id, i]))) + let pendingKey = "" const clearMessageHash = () => { if (!window.location.hash) return @@ -58,7 +58,6 @@ export const useSessionHashScroll = (input: { const index = messageIndex().get(message.id) ?? -1 if (index !== -1 && index < input.turnStart()) { input.setTurnStart(index) - input.scheduleTurnBackfill() requestAnimationFrame(() => { const el = document.getElementById(input.anchor(message.id)) @@ -132,15 +131,6 @@ export const useSessionHashScroll = (input: { if (el) input.scheduleScrollState(el) } - createEffect( - on(input.sessionKey, (key) => { - if (!input.sessionID()) return - const messageID = input.consumePendingMessage(key) - if (!messageID) return - input.setPendingMessage(messageID) - }), - ) - createEffect(() => { if (!input.sessionID() || !input.messagesReady()) return requestAnimationFrame(() => applyHash("auto")) @@ -152,7 +142,20 @@ export const useSessionHashScroll = (input: { visibleUserMessages() input.turnStart() - const targetId = input.pendingMessage() ?? messageIdFromHash(window.location.hash) + let targetId = input.pendingMessage() + if (!targetId) { + const key = input.sessionKey() + if (pendingKey !== key) { + pendingKey = key + const next = input.consumePendingMessage(key) + if (next) { + input.setPendingMessage(next) + targetId = next + } + } + } + + if (!targetId) targetId = messageIdFromHash(window.location.hash) if (!targetId) return if (input.currentMessageId() === targetId) return @@ -164,9 +167,16 @@ export const useSessionHashScroll = (input: { requestAnimationFrame(() => scrollToMessage(msg, "auto")) }) - createEffect(() => { - if (!input.sessionID() || !input.messagesReady()) return - const handler = () => requestAnimationFrame(() => applyHash("auto")) + onMount(() => { + if (typeof window !== "undefined" && "scrollRestoration" in window.history) { + window.history.scrollRestoration = "manual" + } + + const handler = () => { + if (!input.sessionID() || !input.messagesReady()) return + requestAnimationFrame(() => applyHash("auto")) + } + window.addEventListener("hashchange", handler) onCleanup(() => window.removeEventListener("hashchange", handler)) }) diff --git a/packages/app/src/utils/notification-click.test.ts b/packages/app/src/utils/notification-click.test.ts index 76535f83a8..fa81b0e025 100644 --- a/packages/app/src/utils/notification-click.test.ts +++ b/packages/app/src/utils/notification-click.test.ts @@ -1,26 +1,27 @@ -import { describe, expect, test } from "bun:test" -import { handleNotificationClick } from "./notification-click" +import { afterEach, describe, expect, test } from "bun:test" +import { handleNotificationClick, setNavigate } from "./notification-click" describe("notification click", () => { - test("focuses and navigates when href exists", () => { - const calls: string[] = [] - handleNotificationClick("/abc/session/123", { - focus: () => calls.push("focus"), - location: { - assign: (href) => calls.push(href), - }, - }) - expect(calls).toEqual(["focus", "/abc/session/123"]) + afterEach(() => { + setNavigate(undefined as any) }) - test("only focuses when href is missing", () => { + test("navigates via registered navigate function", () => { const calls: string[] = [] - handleNotificationClick(undefined, { - focus: () => calls.push("focus"), - location: { - assign: (href) => calls.push(href), - }, - }) - expect(calls).toEqual(["focus"]) + setNavigate((href) => calls.push(href)) + handleNotificationClick("/abc/session/123") + expect(calls).toEqual(["/abc/session/123"]) + }) + + test("does not navigate when href is missing", () => { + const calls: string[] = [] + setNavigate((href) => calls.push(href)) + handleNotificationClick(undefined) + expect(calls).toEqual([]) + }) + + test("falls back to location.assign without registered navigate", () => { + handleNotificationClick("/abc/session/123") + // falls back to window.location.assign — no error thrown }) }) diff --git a/packages/app/src/utils/notification-click.ts b/packages/app/src/utils/notification-click.ts index 1234cd1d62..94086c5959 100644 --- a/packages/app/src/utils/notification-click.ts +++ b/packages/app/src/utils/notification-click.ts @@ -1,12 +1,12 @@ -type WindowTarget = { - focus: () => void - location: { - assign: (href: string) => void - } +let nav: ((href: string) => void) | undefined + +export const setNavigate = (fn: (href: string) => void) => { + nav = fn } -export const handleNotificationClick = (href?: string, target: WindowTarget = window) => { - target.focus() +export const handleNotificationClick = (href?: string) => { + window.focus() if (!href) return - target.location.assign(href) + if (nav) nav(href) + else window.location.assign(href) } diff --git a/packages/console/app/package.json b/packages/console/app/package.json index ad5813ced6..c2e847991c 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.2.15", + "version": "1.2.16", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/console/app/src/app.tsx b/packages/console/app/src/app.tsx index 3eb70606a4..1f1d0066ec 100644 --- a/packages/console/app/src/app.tsx +++ b/packages/console/app/src/app.tsx @@ -7,9 +7,21 @@ import { Font } from "@opencode-ai/ui/font" import "@ibm/plex/css/ibm-plex.css" import "./app.css" import { LanguageProvider } from "~/context/language" -import { I18nProvider } from "~/context/i18n" +import { I18nProvider, useI18n } from "~/context/i18n" import { strip } from "~/lib/language" +function AppMeta() { + const i18n = useI18n() + return ( + <> + opencode + + + + + ) +} + export default function App() { return ( - opencode - - - + {props.children} diff --git a/packages/console/app/src/component/header.tsx b/packages/console/app/src/component/header.tsx index 6fa0f43ad8..6ab5ce2f51 100644 --- a/packages/console/app/src/component/header.tsx +++ b/packages/console/app/src/component/header.tsx @@ -124,8 +124,8 @@ export function Header(props: { zen?: boolean; hideGetStarted?: boolean }) {
diff --git a/packages/console/app/src/i18n/ar.ts b/packages/console/app/src/i18n/ar.ts index cda1e2a363..0155baf031 100644 --- a/packages/console/app/src/i18n/ar.ts +++ b/packages/console/app/src/i18n/ar.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "الرئيسية", "nav.openMenu": "فتح القائمة", "nav.getStartedFree": "ابدأ مجانا", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "نسخ الشعار كـ SVG", "nav.context.copyWordmark": "نسخ اسم العلامة كـ SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "الوثائق", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "شعار opencode الفاتح", + "notFound.logoDarkAlt": "شعار opencode الداكن", "user.logout": "تسجيل الخروج", + "auth.callback.error.codeMissing": "لم يتم العثور على رمز التفويض.", + "workspace.select": "اختر مساحة العمل", "workspace.createNew": "+ إنشاء مساحة عمل جديدة", "workspace.modal.title": "إنشاء مساحة عمل جديدة", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "يجب أن يكون مبلغ الشحن ${{amount}} على الأقل", "error.reloadTriggerMin": "يجب أن يكون حد الرصيد ${{amount}} على الأقل", + "app.meta.description": "OpenCode - وكيل البرمجة مفتوح المصدر.", + "home.title": "OpenCode | وكيل برمجة بالذكاء الاصطناعي مفتوح المصدر", "temp.title": "opencode | وكيل برمجة بالذكاء الاصطناعي مبني للطرفية", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": "، بما في ذلك النماذج المحلية", "temp.screenshot.caption": "واجهة OpenCode الطرفية مع سمة tokyonight", "temp.screenshot.alt": "واجهة OpenCode الطرفية بسمة tokyonight", + "temp.logoLightAlt": "شعار opencode الفاتح", + "temp.logoDarkAlt": "شعار opencode الداكن", "home.banner.badge": "جديد", "home.banner.text": "تطبيق سطح المكتب متاح بنسخة تجريبية", @@ -238,6 +247,24 @@ export const dict = { "تتم استضافة جميع نماذج Zen في الولايات المتحدة. يتبع المزودون سياسة عدم الاحتفاظ بالبيانات ولا يستخدمون بياناتك لتدريب النماذج، مع", "zen.privacy.exceptionsLink": "الاستثناءات التالية", + "zen.api.error.rateLimitExceeded": "تم تجاوز حد الطلبات. يرجى المحاولة مرة أخرى لاحقًا.", + "zen.api.error.modelNotSupported": "النموذج {{model}} غير مدعوم", + "zen.api.error.modelFormatNotSupported": "النموذج {{model}} غير مدعوم للتنسيق {{format}}", + "zen.api.error.noProviderAvailable": "لا يوجد مزود متاح", + "zen.api.error.providerNotSupported": "المزود {{provider}} غير مدعوم", + "zen.api.error.missingApiKey": "مفتاح API مفقود.", + "zen.api.error.invalidApiKey": "مفتاح API غير صالح.", + "zen.api.error.subscriptionQuotaExceeded": "تم تجاوز حصة الاشتراك. أعد المحاولة خلال {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "تم تجاوز حصة الاشتراك. يمكنك الاستمرار في استخدام النماذج المجانية.", + "zen.api.error.noPaymentMethod": "لا توجد طريقة دفع. أضف طريقة دفع هنا: {{billingUrl}}", + "zen.api.error.insufficientBalance": "رصيد غير كاف. إدارة فواتيرك هنا: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "وصلت مساحة العمل الخاصة بك إلى حد الإنفاق الشهري البالغ ${{amount}}. إدارة حدودك هنا: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "لقد وصلت إلى حد الإنفاق الشهري البالغ ${{amount}}. إدارة حدودك هنا: {{membersUrl}}", + "zen.api.error.modelDisabled": "النموذج معطل", + "black.meta.title": "OpenCode Black | الوصول إلى أفضل نماذج البرمجة في العالم", "black.meta.description": "احصل على وصول إلى Claude، GPT، Gemini والمزيد مع خطط اشتراك OpenCode Black.", "black.hero.title": "الوصول إلى أفضل نماذج البرمجة في العالم", @@ -446,6 +473,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "يرجى تحديث طريقة الدفع والمحاولة مرة أخرى.", "workspace.reload.retrying": "جارٍ إعادة المحاولة...", "workspace.reload.retry": "أعد المحاولة", + "workspace.reload.error.paymentFailed": "فشلت عملية الدفع.", "workspace.payments.title": "سجل المدفوعات", "workspace.payments.subtitle": "معاملات الدفع الأخيرة.", @@ -563,6 +591,10 @@ export const dict = { "enterprise.form.send": "إرسال", "enterprise.form.sending": "جارٍ الإرسال...", "enterprise.form.success": "تم إرسال الرسالة، سنتواصل معك قريبًا.", + "enterprise.form.success.submitted": "تم إرسال النموذج بنجاح.", + "enterprise.form.error.allFieldsRequired": "جميع الحقول مطلوبة.", + "enterprise.form.error.invalidEmailFormat": "تنسيق البريد الإلكتروني غير صالح.", + "enterprise.form.error.internalServer": "خطأ داخلي في الخادم.", "enterprise.faq.title": "الأسئلة الشائعة", "enterprise.faq.q1": "ما هو OpenCode Enterprise؟", "enterprise.faq.a1": @@ -595,6 +627,7 @@ export const dict = { "bench.list.table.agent": "الوكيل", "bench.list.table.model": "النموذج", "bench.list.table.score": "الدرجة", + "bench.submission.error.allFieldsRequired": "جميع الحقول مطلوبة.", "bench.detail.title": "المعيار - {{task}}", "bench.detail.notFound": "المهمة غير موجودة", diff --git a/packages/console/app/src/i18n/br.ts b/packages/console/app/src/i18n/br.ts index ddeb0c10a9..b28c5f45ad 100644 --- a/packages/console/app/src/i18n/br.ts +++ b/packages/console/app/src/i18n/br.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Início", "nav.openMenu": "Abrir menu", "nav.getStartedFree": "Começar grátis", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Copiar logo como SVG", "nav.context.copyWordmark": "Copiar marca como SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Documentação", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "logo opencode claro", + "notFound.logoDarkAlt": "logo opencode escuro", "user.logout": "Sair", + "auth.callback.error.codeMissing": "Nenhum código de autorização encontrado.", + "workspace.select": "Selecionar workspace", "workspace.createNew": "+ Criar novo workspace", "workspace.modal.title": "Criar novo workspace", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "O valor de recarga deve ser de pelo menos ${{amount}}", "error.reloadTriggerMin": "O gatilho de saldo deve ser de pelo menos ${{amount}}", + "app.meta.description": "OpenCode - O agente de codificação de código aberto.", + "home.title": "OpenCode | O agente de codificação de código aberto com IA", "temp.title": "opencode | Agente de codificação com IA feito para o terminal", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", incluindo modelos locais", "temp.screenshot.caption": "OpenCode TUI com o tema tokyonight", "temp.screenshot.alt": "OpenCode TUI com tema tokyonight", + "temp.logoLightAlt": "logo opencode claro", + "temp.logoDarkAlt": "logo opencode escuro", "home.banner.badge": "Novo", "home.banner.text": "App desktop disponível em beta", @@ -242,6 +251,24 @@ export const dict = { "Todos os modelos Zen são hospedados nos EUA. Os provedores seguem uma política de retenção zero e não usam seus dados para treinamento de modelo, com as", "zen.privacy.exceptionsLink": "seguintes exceções", + "zen.api.error.rateLimitExceeded": "Limite de taxa excedido. Por favor, tente novamente mais tarde.", + "zen.api.error.modelNotSupported": "Modelo {{model}} não suportado", + "zen.api.error.modelFormatNotSupported": "Modelo {{model}} não suportado para o formato {{format}}", + "zen.api.error.noProviderAvailable": "Nenhum provedor disponível", + "zen.api.error.providerNotSupported": "Provedor {{provider}} não suportado", + "zen.api.error.missingApiKey": "Chave de API ausente.", + "zen.api.error.invalidApiKey": "Chave de API inválida.", + "zen.api.error.subscriptionQuotaExceeded": "Cota de assinatura excedida. Tente novamente em {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Cota de assinatura excedida. Você pode continuar usando modelos gratuitos.", + "zen.api.error.noPaymentMethod": "Nenhuma forma de pagamento. Adicione uma forma de pagamento aqui: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Saldo insuficiente. Gerencie seu faturamento aqui: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Seu workspace atingiu o limite de gastos mensais de ${{amount}}. Gerencie seus limites aqui: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Você atingiu seu limite de gastos mensais de ${{amount}}. Gerencie seus limites aqui: {{membersUrl}}", + "zen.api.error.modelDisabled": "O modelo está desabilitado", + "black.meta.title": "OpenCode Black | Acesse os melhores modelos de codificação do mundo", "black.meta.description": "Tenha acesso ao Claude, GPT, Gemini e mais com os planos de assinatura OpenCode Black.", "black.hero.title": "Acesse os melhores modelos de codificação do mundo", @@ -451,6 +478,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Por favor, atualize sua forma de pagamento e tente novamente.", "workspace.reload.retrying": "Tentando novamente...", "workspace.reload.retry": "Tentar novamente", + "workspace.reload.error.paymentFailed": "Pagamento falhou.", "workspace.payments.title": "Histórico de Pagamentos", "workspace.payments.subtitle": "Transações de pagamento recentes.", @@ -571,6 +599,10 @@ export const dict = { "enterprise.form.send": "Enviar", "enterprise.form.sending": "Enviando...", "enterprise.form.success": "Mensagem enviada, entraremos em contato em breve.", + "enterprise.form.success.submitted": "Formulário enviado com sucesso.", + "enterprise.form.error.allFieldsRequired": "Todos os campos são obrigatórios.", + "enterprise.form.error.invalidEmailFormat": "Formato de e-mail inválido.", + "enterprise.form.error.internalServer": "Erro interno do servidor.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "O que é OpenCode Enterprise?", "enterprise.faq.a1": @@ -603,6 +635,7 @@ export const dict = { "bench.list.table.agent": "Agente", "bench.list.table.model": "Modelo", "bench.list.table.score": "Pontuação", + "bench.submission.error.allFieldsRequired": "Todos os campos são obrigatórios.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Tarefa não encontrada", diff --git a/packages/console/app/src/i18n/da.ts b/packages/console/app/src/i18n/da.ts index 18b2b89ff9..dfcefc5b9c 100644 --- a/packages/console/app/src/i18n/da.ts +++ b/packages/console/app/src/i18n/da.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Hjem", "nav.openMenu": "Åbn menu", "nav.getStartedFree": "Kom i gang gratis", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Kopier logo som SVG", "nav.context.copyWordmark": "Kopier wordmark som SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Dokumentation", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode logo light", + "notFound.logoDarkAlt": "opencode logo dark", "user.logout": "Log ud", + "auth.callback.error.codeMissing": "Ingen autorisationskode fundet.", + "workspace.select": "Vælg workspace", "workspace.createNew": "+ Opret nyt workspace", "workspace.modal.title": "Opret nyt workspace", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "Genopfyldningsbeløb skal være mindst ${{amount}}", "error.reloadTriggerMin": "Saldogrænse skal være mindst ${{amount}}", + "app.meta.description": "OpenCode - Den open source kodningsagent.", + "home.title": "OpenCode | Den open source AI-kodningsagent", "temp.title": "opencode | AI-kodningsagent bygget til terminalen", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", inklusive lokale modeller", "temp.screenshot.caption": "opencode TUI med tokyonight-temaet", "temp.screenshot.alt": "opencode TUI med tokyonight-temaet", + "temp.logoLightAlt": "opencode logo light", + "temp.logoDarkAlt": "opencode logo dark", "home.banner.badge": "Ny", "home.banner.text": "Desktop-app tilgængelig i beta", @@ -240,6 +249,24 @@ export const dict = { "Alle Zen-modeller er hostet i USA. Udbydere følger en nulopbevaringspolitik og bruger ikke dine data til modeltræning med", "zen.privacy.exceptionsLink": "følgende undtagelser", + "zen.api.error.rateLimitExceeded": "Hastighedsgrænse overskredet. Prøv venligst igen senere.", + "zen.api.error.modelNotSupported": "Model {{model}} understøttes ikke", + "zen.api.error.modelFormatNotSupported": "Model {{model}} understøttes ikke for format {{format}}", + "zen.api.error.noProviderAvailable": "Ingen udbyder tilgængelig", + "zen.api.error.providerNotSupported": "Udbyder {{provider}} understøttes ikke", + "zen.api.error.missingApiKey": "Manglende API-nøgle.", + "zen.api.error.invalidApiKey": "Ugyldig API-nøgle.", + "zen.api.error.subscriptionQuotaExceeded": "Abonnementskvote overskredet. Prøv igen om {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Abonnementskvote overskredet. Du kan fortsætte med at bruge gratis modeller.", + "zen.api.error.noPaymentMethod": "Ingen betalingsmetode. Tilføj en betalingsmetode her: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Utilstrækkelig saldo. Administrer din fakturering her: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Dit workspace har nået sin månedlige forbrugsgrænse på ${{amount}}. Administrer dine grænser her: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Du har nået din månedlige forbrugsgrænse på ${{amount}}. Administrer dine grænser her: {{membersUrl}}", + "zen.api.error.modelDisabled": "Modellen er deaktiveret", + "black.meta.title": "OpenCode Black | Få adgang til verdens bedste kodningsmodeller", "black.meta.description": "Få adgang til Claude, GPT, Gemini og mere med OpenCode Black-abonnementer.", "black.hero.title": "Få adgang til verdens bedste kodningsmodeller", @@ -449,6 +476,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Opdater din betalingsmetode, og prøv igen.", "workspace.reload.retrying": "Prøver igen...", "workspace.reload.retry": "Prøv igen", + "workspace.reload.error.paymentFailed": "Betaling mislykkedes.", "workspace.payments.title": "Betalingshistorik", "workspace.payments.subtitle": "Seneste betalingstransaktioner.", @@ -567,6 +595,10 @@ export const dict = { "enterprise.form.send": "Send", "enterprise.form.sending": "Sender...", "enterprise.form.success": "Besked sendt, vi vender tilbage snart.", + "enterprise.form.success.submitted": "Formular indsendt med succes.", + "enterprise.form.error.allFieldsRequired": "Alle felter er påkrævet.", + "enterprise.form.error.invalidEmailFormat": "Ugyldigt e-mailformat.", + "enterprise.form.error.internalServer": "Intern serverfejl.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Hvad er OpenCode Enterprise?", "enterprise.faq.a1": @@ -599,6 +631,7 @@ export const dict = { "bench.list.table.agent": "Agent", "bench.list.table.model": "Model", "bench.list.table.score": "Score", + "bench.submission.error.allFieldsRequired": "Alle felter er påkrævet.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Opgave ikke fundet", diff --git a/packages/console/app/src/i18n/de.ts b/packages/console/app/src/i18n/de.ts index 5bee74aed3..b5d8070aec 100644 --- a/packages/console/app/src/i18n/de.ts +++ b/packages/console/app/src/i18n/de.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Startseite", "nav.openMenu": "Menü öffnen", "nav.getStartedFree": "Kostenlos starten", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Logo als SVG kopieren", "nav.context.copyWordmark": "Wortmarke als SVG kopieren", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Dokumentation", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "OpenCode Logo hell", + "notFound.logoDarkAlt": "OpenCode Logo dunkel", "user.logout": "Abmelden", + "auth.callback.error.codeMissing": "Kein Autorisierungscode gefunden.", + "workspace.select": "Workspace auswählen", "workspace.createNew": "+ Neuen Workspace erstellen", "workspace.modal.title": "Neuen Workspace erstellen", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "Aufladebetrag muss mindestens ${{amount}} betragen", "error.reloadTriggerMin": "Guthaben-Auslöser muss mindestens ${{amount}} betragen", + "app.meta.description": "OpenCode - Der Open-Source Coding-Agent.", + "home.title": "OpenCode | Der Open-Source AI-Coding-Agent", "temp.title": "OpenCode | Für das Terminal gebauter AI-Coding-Agent", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", einschließlich lokaler Modelle", "temp.screenshot.caption": "OpenCode TUI mit dem Tokyonight-Theme", "temp.screenshot.alt": "OpenCode TUI mit Tokyonight-Theme", + "temp.logoLightAlt": "OpenCode Logo hell", + "temp.logoDarkAlt": "OpenCode Logo dunkel", "home.banner.badge": "Neu", "home.banner.text": "Desktop-App in der Beta verfügbar", @@ -242,6 +251,24 @@ export const dict = { "Alle Zen-Modelle werden in den USA gehostet. Anbieter folgen einer Zero-Retention-Policy und nutzen deine Daten nicht für Modelltraining, mit den", "zen.privacy.exceptionsLink": "folgenden Ausnahmen", + "zen.api.error.rateLimitExceeded": "Ratenlimit überschritten. Bitte versuche es später erneut.", + "zen.api.error.modelNotSupported": "Modell {{model}} wird nicht unterstützt", + "zen.api.error.modelFormatNotSupported": "Modell {{model}} wird für das Format {{format}} nicht unterstützt", + "zen.api.error.noProviderAvailable": "Kein Anbieter verfügbar", + "zen.api.error.providerNotSupported": "Anbieter {{provider}} wird nicht unterstützt", + "zen.api.error.missingApiKey": "Fehlender API-Key.", + "zen.api.error.invalidApiKey": "Ungültiger API-Key.", + "zen.api.error.subscriptionQuotaExceeded": "Abonnement-Quote überschritten. Erneuter Versuch in {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Abonnement-Quote überschritten. Du kannst weiterhin kostenlose Modelle nutzen.", + "zen.api.error.noPaymentMethod": "Keine Zahlungsmethode. Füge hier eine Zahlungsmethode hinzu: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Unzureichendes Guthaben. Verwalte deine Abrechnung hier: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Dein Workspace hat sein monatliches Ausgabenlimit von ${{amount}} erreicht. Verwalte deine Limits hier: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Du hast dein monatliches Ausgabenlimit von ${{amount}} erreicht. Verwalte deine Limits hier: {{membersUrl}}", + "zen.api.error.modelDisabled": "Modell ist deaktiviert", + "black.meta.title": "OpenCode Black | Zugriff auf die weltweit besten Coding-Modelle", "black.meta.description": "Erhalte Zugriff auf Claude, GPT, Gemini und mehr mit OpenCode Black Abos.", "black.hero.title": "Zugriff auf die weltweit besten Coding-Modelle", @@ -451,6 +478,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Bitte aktualisiere deine Zahlungsmethode und versuche es erneut.", "workspace.reload.retrying": "Versuche erneut...", "workspace.reload.retry": "Erneut versuchen", + "workspace.reload.error.paymentFailed": "Zahlung fehlgeschlagen.", "workspace.payments.title": "Zahlungshistorie", "workspace.payments.subtitle": "Kürzliche Zahlungstransaktionen.", @@ -571,6 +599,10 @@ export const dict = { "enterprise.form.send": "Senden", "enterprise.form.sending": "Sende...", "enterprise.form.success": "Nachricht gesendet, wir melden uns bald.", + "enterprise.form.success.submitted": "Formular erfolgreich gesendet.", + "enterprise.form.error.allFieldsRequired": "Alle Felder sind erforderlich.", + "enterprise.form.error.invalidEmailFormat": "Ungültiges E-Mail-Format.", + "enterprise.form.error.internalServer": "Interner Serverfehler.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Was ist OpenCode Enterprise?", "enterprise.faq.a1": @@ -603,6 +635,7 @@ export const dict = { "bench.list.table.agent": "Agent", "bench.list.table.model": "Modell", "bench.list.table.score": "Score", + "bench.submission.error.allFieldsRequired": "Alle Felder sind erforderlich.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Task nicht gefunden", diff --git a/packages/console/app/src/i18n/en.ts b/packages/console/app/src/i18n/en.ts index d6db2e7f8a..07a4ddb4c2 100644 --- a/packages/console/app/src/i18n/en.ts +++ b/packages/console/app/src/i18n/en.ts @@ -11,6 +11,7 @@ export const dict = { "nav.home": "Home", "nav.openMenu": "Open menu", "nav.getStartedFree": "Get started for free", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Copy logo as SVG", "nav.context.copyWordmark": "Copy wordmark as SVG", @@ -38,9 +39,13 @@ export const dict = { "notFound.docs": "Docs", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode logo light", + "notFound.logoDarkAlt": "opencode logo dark", "user.logout": "Logout", + "auth.callback.error.codeMissing": "No authorization code found.", + "workspace.select": "Select workspace", "workspace.createNew": "+ Create New Workspace", "workspace.modal.title": "Create New Workspace", @@ -72,6 +77,8 @@ export const dict = { "error.reloadAmountMin": "Reload amount must be at least ${{amount}}", "error.reloadTriggerMin": "Balance trigger must be at least ${{amount}}", + "app.meta.description": "OpenCode - The open source coding agent.", + "home.title": "OpenCode | The open source AI coding agent", "temp.title": "opencode | AI coding agent built for the terminal", @@ -87,6 +94,8 @@ export const dict = { "temp.feature.models.afterLink": ", including local models", "temp.screenshot.caption": "opencode TUI with the tokyonight theme", "temp.screenshot.alt": "opencode TUI with tokyonight theme", + "temp.logoLightAlt": "opencode logo light", + "temp.logoDarkAlt": "opencode logo dark", "home.banner.badge": "New", "home.banner.text": "Desktop app available in beta", @@ -234,6 +243,24 @@ export const dict = { "All Zen models are hosted in the US. Providers follow a zero-retention policy and do not use your data for model training, with the", "zen.privacy.exceptionsLink": "following exceptions", + "zen.api.error.rateLimitExceeded": "Rate limit exceeded. Please try again later.", + "zen.api.error.modelNotSupported": "Model {{model}} not supported", + "zen.api.error.modelFormatNotSupported": "Model {{model}} not supported for format {{format}}", + "zen.api.error.noProviderAvailable": "No provider available", + "zen.api.error.providerNotSupported": "Provider {{provider}} not supported", + "zen.api.error.missingApiKey": "Missing API key.", + "zen.api.error.invalidApiKey": "Invalid API key.", + "zen.api.error.subscriptionQuotaExceeded": "Subscription quota exceeded. Retry in {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Subscription quota exceeded. You can continue using free models.", + "zen.api.error.noPaymentMethod": "No payment method. Add a payment method here: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Insufficient balance. Manage your billing here: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Your workspace has reached its monthly spending limit of ${{amount}}. Manage your limits here: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "You have reached your monthly spending limit of ${{amount}}. Manage your limits here: {{membersUrl}}", + "zen.api.error.modelDisabled": "Model is disabled", + "black.meta.title": "OpenCode Black | Access all the world's best coding models", "black.meta.description": "Get access to Claude, GPT, Gemini and more with OpenCode Black subscription plans.", "black.hero.title": "Access all the world's best coding models", @@ -443,6 +470,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Please update your payment method and try again.", "workspace.reload.retrying": "Retrying...", "workspace.reload.retry": "Retry", + "workspace.reload.error.paymentFailed": "Payment failed.", "workspace.payments.title": "Payments History", "workspace.payments.subtitle": "Recent payment transactions.", @@ -561,6 +589,10 @@ export const dict = { "enterprise.form.send": "Send", "enterprise.form.sending": "Sending...", "enterprise.form.success": "Message sent, we'll be in touch soon.", + "enterprise.form.success.submitted": "Form submitted successfully.", + "enterprise.form.error.allFieldsRequired": "All fields are required.", + "enterprise.form.error.invalidEmailFormat": "Invalid email format.", + "enterprise.form.error.internalServer": "Internal server error.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "What is OpenCode Enterprise?", "enterprise.faq.a1": @@ -593,6 +625,7 @@ export const dict = { "bench.list.table.agent": "Agent", "bench.list.table.model": "Model", "bench.list.table.score": "Score", + "bench.submission.error.allFieldsRequired": "All fields are required.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Task not found", diff --git a/packages/console/app/src/i18n/es.ts b/packages/console/app/src/i18n/es.ts index c4676fe6e9..65c81648be 100644 --- a/packages/console/app/src/i18n/es.ts +++ b/packages/console/app/src/i18n/es.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Inicio", "nav.openMenu": "Abrir menú", "nav.getStartedFree": "Empezar gratis", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Copiar logo como SVG", "nav.context.copyWordmark": "Copiar marca como SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Documentación", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode logo claro", + "notFound.logoDarkAlt": "opencode logo oscuro", "user.logout": "Cerrar sesión", + "auth.callback.error.codeMissing": "No se encontró código de autorización.", + "workspace.select": "Seleccionar espacio de trabajo", "workspace.createNew": "+ Crear nuevo espacio de trabajo", "workspace.modal.title": "Crear nuevo espacio de trabajo", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "La cantidad de recarga debe ser al menos ${{amount}}", "error.reloadTriggerMin": "El disparador de saldo debe ser al menos ${{amount}}", + "app.meta.description": "OpenCode - El agente de codificación de código abierto.", + "home.title": "OpenCode | El agente de codificación IA de código abierto", "temp.title": "opencode | Agente de codificación IA creado para la terminal", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", incluyendo modelos locales", "temp.screenshot.caption": "opencode TUI con el tema tokyonight", "temp.screenshot.alt": "opencode TUI con tema tokyonight", + "temp.logoLightAlt": "logo de opencode claro", + "temp.logoDarkAlt": "logo de opencode oscuro", "home.banner.badge": "Nuevo", "home.banner.text": "Aplicación de escritorio disponible en beta", @@ -243,6 +252,24 @@ export const dict = { "Todos los modelos Zen están alojados en EE. UU. Los proveedores siguen una política de cero retención y no usan tus datos para entrenamiento de modelos, con las", "zen.privacy.exceptionsLink": "siguientes excepciones", + "zen.api.error.rateLimitExceeded": "Límite de tasa excedido. Por favor, inténtalo de nuevo más tarde.", + "zen.api.error.modelNotSupported": "Modelo {{model}} no soportado", + "zen.api.error.modelFormatNotSupported": "Modelo {{model}} no soportado para el formato {{format}}", + "zen.api.error.noProviderAvailable": "Ningún proveedor disponible", + "zen.api.error.providerNotSupported": "Proveedor {{provider}} no soportado", + "zen.api.error.missingApiKey": "Falta la clave API.", + "zen.api.error.invalidApiKey": "Clave API inválida.", + "zen.api.error.subscriptionQuotaExceeded": "Cuota de suscripción excedida. Reintenta en {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Cuota de suscripción excedida. Puedes continuar usando modelos gratuitos.", + "zen.api.error.noPaymentMethod": "Sin método de pago. Añade un método de pago aquí: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Saldo insuficiente. Gestiona tu facturación aquí: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Tu espacio de trabajo ha alcanzado su límite de gasto mensual de ${{amount}}. Gestiona tus límites aquí: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Has alcanzado tu límite de gasto mensual de ${{amount}}. Gestiona tus límites aquí: {{membersUrl}}", + "zen.api.error.modelDisabled": "El modelo está deshabilitado", + "black.meta.title": "OpenCode Black | Accede a los mejores modelos de codificación del mundo", "black.meta.description": "Obtén acceso a Claude, GPT, Gemini y más con los planes de suscripción de OpenCode Black.", "black.hero.title": "Accede a los mejores modelos de codificación del mundo", @@ -452,6 +479,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Por favor actualiza tu método de pago e intenta de nuevo.", "workspace.reload.retrying": "Reintentando...", "workspace.reload.retry": "Reintentar", + "workspace.reload.error.paymentFailed": "El pago falló.", "workspace.payments.title": "Historial de Pagos", "workspace.payments.subtitle": "Transacciones de pago recientes.", @@ -571,6 +599,10 @@ export const dict = { "enterprise.form.send": "Enviar", "enterprise.form.sending": "Enviando...", "enterprise.form.success": "Mensaje enviado, estaremos en contacto pronto.", + "enterprise.form.success.submitted": "Formulario enviado con éxito.", + "enterprise.form.error.allFieldsRequired": "Todos los campos son obligatorios.", + "enterprise.form.error.invalidEmailFormat": "Formato de correo inválido.", + "enterprise.form.error.internalServer": "Error interno del servidor.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "¿Qué es OpenCode Enterprise?", "enterprise.faq.a1": @@ -603,6 +635,7 @@ export const dict = { "bench.list.table.agent": "Agente", "bench.list.table.model": "Modelo", "bench.list.table.score": "Puntuación", + "bench.submission.error.allFieldsRequired": "Todos los campos son obligatorios.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Tarea no encontrada", diff --git a/packages/console/app/src/i18n/fr.ts b/packages/console/app/src/i18n/fr.ts index 7b2306bc2f..bf741aa9d0 100644 --- a/packages/console/app/src/i18n/fr.ts +++ b/packages/console/app/src/i18n/fr.ts @@ -3,6 +3,7 @@ import { dict as en } from "./en" export const dict = { ...en, + "app.meta.description": "OpenCode - L'agent de code open source.", "nav.github": "GitHub", "nav.docs": "Documentation", "nav.changelog": "Changelog", @@ -15,6 +16,7 @@ export const dict = { "nav.home": "Accueil", "nav.openMenu": "Ouvrir le menu", "nav.getStartedFree": "Commencer gratuitement", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Copier le logo en SVG", "nav.context.copyWordmark": "Copier le logotype en SVG", @@ -42,6 +44,8 @@ export const dict = { "notFound.docs": "Documentation", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode logo light", + "notFound.logoDarkAlt": "opencode logo dark", "user.logout": "Se déconnecter", @@ -75,6 +79,7 @@ export const dict = { "error.modelRequired": "Le modèle est requis", "error.reloadAmountMin": "Le montant de recharge doit être d'au moins {{amount}} $", "error.reloadTriggerMin": "Le seuil de déclenchement doit être d'au moins {{amount}} $", + "auth.callback.error.codeMissing": "Aucun code d'autorisation trouvé.", "home.title": "OpenCode | L'agent de code IA open source", @@ -91,6 +96,8 @@ export const dict = { "temp.feature.models.afterLink": ", y compris les modèles locaux", "temp.screenshot.caption": "OpenCode TUI avec le thème tokyonight", "temp.screenshot.alt": "OpenCode TUI avec le thème tokyonight", + "temp.logoLightAlt": "opencode logo light", + "temp.logoDarkAlt": "opencode logo dark", "home.banner.badge": "Nouveau", "home.banner.text": "Application desktop disponible en bêta", @@ -246,6 +253,24 @@ export const dict = { "Tous les modèles Zen sont hébergés aux États-Unis. Les fournisseurs suivent une politique de rétention zéro et n'utilisent pas vos données pour l'entraînement des modèles, avec les", "zen.privacy.exceptionsLink": "exceptions suivantes", + "zen.api.error.rateLimitExceeded": "Limite de débit dépassée. Veuillez réessayer plus tard.", + "zen.api.error.modelNotSupported": "Modèle {{model}} non pris en charge", + "zen.api.error.modelFormatNotSupported": "Modèle {{model}} non pris en charge pour le format {{format}}", + "zen.api.error.noProviderAvailable": "Aucun fournisseur disponible", + "zen.api.error.providerNotSupported": "Fournisseur {{provider}} non pris en charge", + "zen.api.error.missingApiKey": "Clé API manquante.", + "zen.api.error.invalidApiKey": "Clé API invalide.", + "zen.api.error.subscriptionQuotaExceeded": "Quota d'abonnement dépassé. Réessayez dans {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Quota d'abonnement dépassé. Vous pouvez continuer à utiliser les modèles gratuits.", + "zen.api.error.noPaymentMethod": "Aucune méthode de paiement. Ajoutez une méthode de paiement ici : {{billingUrl}}", + "zen.api.error.insufficientBalance": "Solde insuffisant. Gérez votre facturation ici : {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Votre espace de travail a atteint sa limite de dépense mensuelle de {{amount}} $. Gérez vos limites ici : {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Vous avez atteint votre limite de dépense mensuelle de {{amount}} $. Gérez vos limites ici : {{membersUrl}}", + "zen.api.error.modelDisabled": "Le modèle est désactivé", + "black.meta.title": "OpenCode Black | Accédez aux meilleurs modèles de code au monde", "black.meta.description": "Accédez à Claude, GPT, Gemini et plus avec les forfaits d'abonnement OpenCode Black.", "black.hero.title": "Accédez aux meilleurs modèles de code au monde", @@ -457,6 +482,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Veuillez mettre à jour votre méthode de paiement et réessayer.", "workspace.reload.retrying": "Nouvelle tentative...", "workspace.reload.retry": "Réessayer", + "workspace.reload.error.paymentFailed": "Échec du paiement.", "workspace.payments.title": "Historique des paiements", "workspace.payments.subtitle": "Transactions de paiement récentes.", @@ -581,6 +607,10 @@ export const dict = { "enterprise.form.send": "Envoyer", "enterprise.form.sending": "Envoi...", "enterprise.form.success": "Message envoyé, nous vous contacterons bientôt.", + "enterprise.form.success.submitted": "Formulaire soumis avec succès.", + "enterprise.form.error.allFieldsRequired": "Tous les champs sont requis.", + "enterprise.form.error.invalidEmailFormat": "Format d'e-mail invalide.", + "enterprise.form.error.internalServer": "Erreur interne du serveur.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Qu'est-ce que OpenCode Enterprise ?", "enterprise.faq.a1": @@ -640,4 +670,5 @@ export const dict = { "bench.detail.table.duration": "Durée", "bench.detail.run.title": "Exécution {{n}}", "bench.detail.rawJson": "JSON brut", + "bench.submission.error.allFieldsRequired": "Tous les champs sont requis.", } satisfies Dict diff --git a/packages/console/app/src/i18n/it.ts b/packages/console/app/src/i18n/it.ts index 81dd293057..0a9e4f9592 100644 --- a/packages/console/app/src/i18n/it.ts +++ b/packages/console/app/src/i18n/it.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Home", "nav.openMenu": "Apri menu", "nav.getStartedFree": "Inizia gratis", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Copia il logo come SVG", "nav.context.copyWordmark": "Copia il wordmark come SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Documentazione", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "logo chiaro di opencode", + "notFound.logoDarkAlt": "logo scuro di opencode", "user.logout": "Esci", + "auth.callback.error.codeMissing": "Nessun codice di autorizzazione trovato.", + "workspace.select": "Seleziona workspace", "workspace.createNew": "+ Crea nuovo workspace", "workspace.modal.title": "Crea nuovo workspace", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "L'importo della ricarica deve essere almeno ${{amount}}", "error.reloadTriggerMin": "La soglia del saldo deve essere almeno ${{amount}}", + "app.meta.description": "OpenCode - L'agente di programmazione open source.", + "home.title": "OpenCode | L'agente di coding IA open source", "temp.title": "opencode | Agente di coding IA costruito per il terminale", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", inclusi modelli locali", "temp.screenshot.caption": "OpenCode TUI con il tema tokyonight", "temp.screenshot.alt": "OpenCode TUI con tema tokyonight", + "temp.logoLightAlt": "logo chiaro di opencode", + "temp.logoDarkAlt": "logo scuro di opencode", "home.banner.badge": "Nuovo", "home.banner.text": "App desktop disponibile in beta", @@ -240,6 +249,24 @@ export const dict = { "Tutti i modelli Zen sono ospitati negli Stati Uniti. I provider seguono una policy di zero-retention e non usano i tuoi dati per l'addestramento dei modelli, con le", "zen.privacy.exceptionsLink": "seguenti eccezioni", + "zen.api.error.rateLimitExceeded": "Limite di richieste superato. Riprova più tardi.", + "zen.api.error.modelNotSupported": "Modello {{model}} non supportato", + "zen.api.error.modelFormatNotSupported": "Modello {{model}} non supportato per il formato {{format}}", + "zen.api.error.noProviderAvailable": "Nessun provider disponibile", + "zen.api.error.providerNotSupported": "Provider {{provider}} non supportato", + "zen.api.error.missingApiKey": "Chiave API mancante.", + "zen.api.error.invalidApiKey": "Chiave API non valida.", + "zen.api.error.subscriptionQuotaExceeded": "Quota dell'abbonamento superata. Riprova tra {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Quota dell'abbonamento superata. Puoi continuare a utilizzare modelli gratuiti.", + "zen.api.error.noPaymentMethod": "Nessun metodo di pagamento. Aggiungi un metodo di pagamento qui: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Saldo insufficiente. Gestisci la tua fatturazione qui: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "La tua area di lavoro ha raggiunto il limite di spesa mensile di ${{amount}}. Gestisci i tuoi limiti qui: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Hai raggiunto il tuo limite di spesa mensile di ${{amount}}. Gestisci i tuoi limiti qui: {{membersUrl}}", + "zen.api.error.modelDisabled": "Il modello è disabilitato", + "black.meta.title": "OpenCode Black | Accedi ai migliori modelli di coding al mondo", "black.meta.description": "Ottieni l'accesso a Claude, GPT, Gemini e altri con i piani di abbonamento OpenCode Black.", @@ -451,6 +478,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Aggiorna il tuo metodo di pagamento e riprova.", "workspace.reload.retrying": "Riprovo...", "workspace.reload.retry": "Riprova", + "workspace.reload.error.paymentFailed": "Pagamento fallito.", "workspace.payments.title": "Cronologia Pagamenti", "workspace.payments.subtitle": "Transazioni di pagamento recenti.", @@ -569,6 +597,10 @@ export const dict = { "enterprise.form.send": "Invia", "enterprise.form.sending": "Invio...", "enterprise.form.success": "Messaggio inviato, ti contatteremo presto.", + "enterprise.form.success.submitted": "Modulo inviato con successo.", + "enterprise.form.error.allFieldsRequired": "Tutti i campi sono obbligatori.", + "enterprise.form.error.invalidEmailFormat": "Formato email non valido.", + "enterprise.form.error.internalServer": "Errore interno del server.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Cos'è OpenCode Enterprise?", "enterprise.faq.a1": @@ -601,6 +633,7 @@ export const dict = { "bench.list.table.agent": "Agente", "bench.list.table.model": "Modello", "bench.list.table.score": "Punteggio", + "bench.submission.error.allFieldsRequired": "Tutti i campi sono obbligatori.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Task non trovato", diff --git a/packages/console/app/src/i18n/ja.ts b/packages/console/app/src/i18n/ja.ts index afcf6aeb9b..ee7b5f9288 100644 --- a/packages/console/app/src/i18n/ja.ts +++ b/packages/console/app/src/i18n/ja.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "ホーム", "nav.openMenu": "メニューを開く", "nav.getStartedFree": "無料ではじめる", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "ロゴをSVGでコピー", "nav.context.copyWordmark": "ワードマークをSVGでコピー", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "ドキュメント", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencodeのロゴ(ライト)", + "notFound.logoDarkAlt": "opencodeのロゴ(ダーク)", "user.logout": "ログアウト", + "auth.callback.error.codeMissing": "認証コードが見つかりません。", + "workspace.select": "ワークスペースを選択", "workspace.createNew": "+ 新しいワークスペースを作成", "workspace.modal.title": "新しいワークスペースを作成", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "リロード額は少なくとも ${{amount}} である必要があります", "error.reloadTriggerMin": "残高トリガーは少なくとも ${{amount}} である必要があります", + "app.meta.description": "OpenCode - オープンソースのコーディングエージェント。", + "home.title": "OpenCode | オープンソースのAIコーディングエージェント", "temp.title": "OpenCode | ターミナル向けに構築されたAIコーディングエージェント", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": "を通じて75以上のLLMプロバイダーをサポート", "temp.screenshot.caption": "tokyonight テーマを使用した OpenCode TUI", "temp.screenshot.alt": "tokyonight テーマの OpenCode TUI", + "temp.logoLightAlt": "opencodeのロゴ(ライト)", + "temp.logoDarkAlt": "opencodeのロゴ(ダーク)", "home.banner.badge": "新着", "home.banner.text": "デスクトップアプリのベータ版が利用可能", @@ -239,6 +248,25 @@ export const dict = { "すべてのZenモデルは米国でホストされています。プロバイダーはゼロ保持ポリシーに従い、モデルのトレーニングにデータを使用しません(", "zen.privacy.exceptionsLink": "以下の例外", + "zen.api.error.rateLimitExceeded": "レート制限を超えました。後でもう一度お試しください。", + "zen.api.error.modelNotSupported": "モデル {{model}} はサポートされていません", + "zen.api.error.modelFormatNotSupported": "フォーマット {{format}} ではモデル {{model}} はサポートされていません", + "zen.api.error.noProviderAvailable": "利用可能なプロバイダーがありません", + "zen.api.error.providerNotSupported": "プロバイダー {{provider}} はサポートされていません", + "zen.api.error.missingApiKey": "APIキーがありません。", + "zen.api.error.invalidApiKey": "無効なAPIキーです。", + "zen.api.error.subscriptionQuotaExceeded": + "サブスクリプションの制限を超えました。{{retryIn}} 後に再試行してください。", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "サブスクリプションの制限を超えました。無料モデルは引き続きご利用いただけます。", + "zen.api.error.noPaymentMethod": "お支払い方法がありません。こちらからお支払い方法を追加してください: {{billingUrl}}", + "zen.api.error.insufficientBalance": "残高が不足しています。こちらから請求を管理してください: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "ワークスペースが月額の利用上限 ${{amount}} に達しました。こちらから上限を管理してください: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "月額の利用上限 ${{amount}} に達しました。こちらから上限を管理してください: {{membersUrl}}", + "zen.api.error.modelDisabled": "モデルが無効です", + "black.meta.title": "OpenCode Black | 世界最高峰のコーディングモデルすべてにアクセス", "black.meta.description": "OpenCode Black サブスクリプションプランで、Claude、GPT、Gemini などにアクセス。", "black.hero.title": "世界最高峰のコーディングモデルすべてにアクセス", @@ -448,6 +476,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "支払い方法を更新して、もう一度お試しください。", "workspace.reload.retrying": "再試行中...", "workspace.reload.retry": "再試行", + "workspace.reload.error.paymentFailed": "支払いに失敗しました。", "workspace.payments.title": "支払い履歴", "workspace.payments.subtitle": "最近の支払い取引。", @@ -568,6 +597,10 @@ export const dict = { "enterprise.form.send": "送信", "enterprise.form.sending": "送信中...", "enterprise.form.success": "送信しました。まもなくご連絡いたします。", + "enterprise.form.success.submitted": "フォームが正常に送信されました。", + "enterprise.form.error.allFieldsRequired": "すべての項目は必須です。", + "enterprise.form.error.invalidEmailFormat": "無効なメール形式です。", + "enterprise.form.error.internalServer": "内部サーバーエラー。", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "OpenCode Enterpriseとは?", "enterprise.faq.a1": @@ -600,6 +633,7 @@ export const dict = { "bench.list.table.agent": "エージェント", "bench.list.table.model": "モデル", "bench.list.table.score": "スコア", + "bench.submission.error.allFieldsRequired": "すべての項目は必須です。", "bench.detail.title": "ベンチマーク - {{task}}", "bench.detail.notFound": "タスクが見つかりません", diff --git a/packages/console/app/src/i18n/ko.ts b/packages/console/app/src/i18n/ko.ts index b2375c3f7d..2dc3f9466c 100644 --- a/packages/console/app/src/i18n/ko.ts +++ b/packages/console/app/src/i18n/ko.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "홈", "nav.openMenu": "메뉴 열기", "nav.getStartedFree": "무료로 시작하기", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "로고를 SVG로 복사", "nav.context.copyWordmark": "워드마크를 SVG로 복사", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "문서", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode 밝은 로고", + "notFound.logoDarkAlt": "opencode 어두운 로고", "user.logout": "로그아웃", + "auth.callback.error.codeMissing": "인증 코드를 찾을 수 없습니다.", + "workspace.select": "워크스페이스 선택", "workspace.createNew": "+ 새 워크스페이스 만들기", "workspace.modal.title": "새 워크스페이스 만들기", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "충전 금액은 최소 ${{amount}}이어야 합니다", "error.reloadTriggerMin": "잔액 트리거는 최소 ${{amount}}이어야 합니다", + "app.meta.description": "OpenCode - 오픈 소스 코딩 에이전트.", + "home.title": "OpenCode | 오픈 소스 AI 코딩 에이전트", "temp.title": "OpenCode | 터미널을 위해 만들어진 AI 코딩 에이전트", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": "를 통해 75개 이상의 LLM 제공자 지원", "temp.screenshot.caption": "tokyonight 테마가 적용된 OpenCode TUI", "temp.screenshot.alt": "tokyonight 테마가 적용된 OpenCode TUI", + "temp.logoLightAlt": "opencode 밝은 로고", + "temp.logoDarkAlt": "opencode 어두운 로고", "home.banner.badge": "신규", "home.banner.text": "데스크톱 앱 베타 버전 출시", @@ -236,6 +245,24 @@ export const dict = { "모든 Zen 모델은 미국에서 호스팅됩니다. 제공자들은 데이터 보존 금지 정책을 따르며 모델 학습에 데이터를 사용하지 않습니다. 단,", "zen.privacy.exceptionsLink": "다음 예외", + "zen.api.error.rateLimitExceeded": "속도 제한을 초과했습니다. 나중에 다시 시도해 주세요.", + "zen.api.error.modelNotSupported": "{{model}} 모델은 지원되지 않습니다", + "zen.api.error.modelFormatNotSupported": "{{model}} 모델은 {{format}} 형식에 대해 지원되지 않습니다", + "zen.api.error.noProviderAvailable": "사용 가능한 제공자가 없습니다", + "zen.api.error.providerNotSupported": "{{provider}} 제공자는 지원되지 않습니다", + "zen.api.error.missingApiKey": "API 키가 누락되었습니다.", + "zen.api.error.invalidApiKey": "유효하지 않은 API 키입니다.", + "zen.api.error.subscriptionQuotaExceeded": "구독 할당량을 초과했습니다. {{retryIn}} 후 다시 시도해 주세요.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "구독 할당량을 초과했습니다. 무료 모델은 계속 사용할 수 있습니다.", + "zen.api.error.noPaymentMethod": "결제 수단이 없습니다. 결제 수단을 추가하세요: {{billingUrl}}", + "zen.api.error.insufficientBalance": "잔액이 부족합니다. 결제 관리를 여기서 하세요: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "워크스페이스의 월간 지출 한도인 ${{amount}}에 도달했습니다. 한도 관리를 여기서 하세요: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "월간 지출 한도인 ${{amount}}에 도달했습니다. 한도 관리를 여기서 하세요: {{membersUrl}}", + "zen.api.error.modelDisabled": "모델이 비활성화되었습니다", + "black.meta.title": "OpenCode Black | 세계 최고의 코딩 모델에 액세스하세요", "black.meta.description": "OpenCode Black 구독 플랜으로 Claude, GPT, Gemini 등에 액세스하세요.", "black.hero.title": "세계 최고의 코딩 모델에 액세스하세요", @@ -445,6 +472,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "결제 수단을 업데이트하고 다시 시도해 주세요.", "workspace.reload.retrying": "재시도 중...", "workspace.reload.retry": "재시도", + "workspace.reload.error.paymentFailed": "결제에 실패했습니다.", "workspace.payments.title": "결제 내역", "workspace.payments.subtitle": "최근 결제 거래 내역입니다.", @@ -562,6 +590,10 @@ export const dict = { "enterprise.form.send": "전송", "enterprise.form.sending": "전송 중...", "enterprise.form.success": "메시지가 전송되었습니다. 곧 연락드리겠습니다.", + "enterprise.form.success.submitted": "양식이 성공적으로 제출되었습니다.", + "enterprise.form.error.allFieldsRequired": "모든 필드는 필수 항목입니다.", + "enterprise.form.error.invalidEmailFormat": "유효하지 않은 이메일 형식입니다.", + "enterprise.form.error.internalServer": "내부 서버 오류입니다.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "OpenCode 엔터프라이즈란 무엇인가요?", "enterprise.faq.a1": @@ -594,6 +626,7 @@ export const dict = { "bench.list.table.agent": "에이전트", "bench.list.table.model": "모델", "bench.list.table.score": "점수", + "bench.submission.error.allFieldsRequired": "모든 필드는 필수 항목입니다.", "bench.detail.title": "벤치마크 - {{task}}", "bench.detail.notFound": "태스크를 찾을 수 없음", diff --git a/packages/console/app/src/i18n/no.ts b/packages/console/app/src/i18n/no.ts index 41bacfb053..35c4bbb6ab 100644 --- a/packages/console/app/src/i18n/no.ts +++ b/packages/console/app/src/i18n/no.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Hjem", "nav.openMenu": "Åpne meny", "nav.getStartedFree": "Kom i gang gratis", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Kopier logo som SVG", "nav.context.copyWordmark": "Kopier wordmark som SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Dokumentasjon", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode logo lys", + "notFound.logoDarkAlt": "opencode logo mørk", "user.logout": "Logg ut", + "auth.callback.error.codeMissing": "Ingen autorisasjonskode funnet.", + "workspace.select": "Velg arbeidsområde", "workspace.createNew": "+ Opprett nytt arbeidsområde", "workspace.modal.title": "Opprett nytt arbeidsområde", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "Påfyllingsbeløp må være minst ${{amount}}", "error.reloadTriggerMin": "Saldo-trigger må være minst ${{amount}}", + "app.meta.description": "OpenCode - Den åpne kildekode kodingsagenten.", + "home.title": "OpenCode | Den åpne kildekode AI-kodingsagenten", "temp.title": "opencode | AI-kodingsagent bygget for terminalen", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", inkludert lokale modeller", "temp.screenshot.caption": "opencode TUI med tokyonight-tema", "temp.screenshot.alt": "opencode TUI med tokyonight-tema", + "temp.logoLightAlt": "opencode logo lys", + "temp.logoDarkAlt": "opencode logo mørk", "home.banner.badge": "Ny", "home.banner.text": "Desktop-app tilgjengelig i beta", @@ -240,6 +249,24 @@ export const dict = { "Alle Zen-modeller hostes i USA. Leverandører følger en policy om null oppbevaring og bruker ikke dataene dine til modelltrening, med", "zen.privacy.exceptionsLink": "følgende unntak", + "zen.api.error.rateLimitExceeded": "Rate limit overskredet. Vennligst prøv igjen senere.", + "zen.api.error.modelNotSupported": "Modell {{model}} støttes ikke", + "zen.api.error.modelFormatNotSupported": "Modell {{model}} støttes ikke for format {{format}}", + "zen.api.error.noProviderAvailable": "Ingen leverandør tilgjengelig", + "zen.api.error.providerNotSupported": "Leverandør {{provider}} støttes ikke", + "zen.api.error.missingApiKey": "Mangler API-nøkkel.", + "zen.api.error.invalidApiKey": "Ugyldig API-nøkkel.", + "zen.api.error.subscriptionQuotaExceeded": "Abonnementskvote overskredet. Prøv igjen om {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Abonnementskvote overskredet. Du kan fortsette å bruke gratis modeller.", + "zen.api.error.noPaymentMethod": "Ingen betalingsmetode. Legg til en betalingsmetode her: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Utilstrekkelig saldo. Administrer faktureringen din her: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Arbeidsområdet ditt har nådd sin månedlige utgiftsgrense på ${{amount}}. Administrer grensene dine her: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Du har nådd din månedlige utgiftsgrense på ${{amount}}. Administrer grensene dine her: {{membersUrl}}", + "zen.api.error.modelDisabled": "Modellen er deaktivert", + "black.meta.title": "OpenCode Black | Få tilgang til verdens beste kodemodeller", "black.meta.description": "Få tilgang til Claude, GPT, Gemini og mer med OpenCode Black-abonnementer.", "black.hero.title": "Få tilgang til verdens beste kodemodeller", @@ -449,6 +476,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Vennligst oppdater betalingsmetoden din og prøv på nytt.", "workspace.reload.retrying": "Prøver på nytt...", "workspace.reload.retry": "Prøv på nytt", + "workspace.reload.error.paymentFailed": "Betaling mislyktes.", "workspace.payments.title": "Betalingshistorikk", "workspace.payments.subtitle": "Nylige betalingstransaksjoner.", @@ -567,6 +595,10 @@ export const dict = { "enterprise.form.send": "Send", "enterprise.form.sending": "Sender...", "enterprise.form.success": "Melding sendt, vi tar kontakt snart.", + "enterprise.form.success.submitted": "Skjemaet ble sendt inn.", + "enterprise.form.error.allFieldsRequired": "Alle felt er obligatoriske.", + "enterprise.form.error.invalidEmailFormat": "Ugyldig e-postformat.", + "enterprise.form.error.internalServer": "Intern serverfeil.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Hva er OpenCode Enterprise?", "enterprise.faq.a1": @@ -599,6 +631,7 @@ export const dict = { "bench.list.table.agent": "Agent", "bench.list.table.model": "Modell", "bench.list.table.score": "Poengsum", + "bench.submission.error.allFieldsRequired": "Alle felt er obligatoriske.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Oppgave ikke funnet", diff --git a/packages/console/app/src/i18n/pl.ts b/packages/console/app/src/i18n/pl.ts index dc3c59196d..0ff5388be9 100644 --- a/packages/console/app/src/i18n/pl.ts +++ b/packages/console/app/src/i18n/pl.ts @@ -14,6 +14,7 @@ export const dict = { "nav.home": "Strona główna", "nav.openMenu": "Otwórz menu", "nav.getStartedFree": "Zacznij za darmo", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Skopiuj logo jako SVG", "nav.context.copyWordmark": "Skopiuj logotyp jako SVG", @@ -41,9 +42,13 @@ export const dict = { "notFound.docs": "Dokumentacja", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "jasne logo opencode", + "notFound.logoDarkAlt": "ciemne logo opencode", "user.logout": "Wyloguj się", + "auth.callback.error.codeMissing": "Nie znaleziono kodu autoryzacji.", + "workspace.select": "Wybierz obszar roboczy", "workspace.createNew": "+ Utwórz nowy obszar roboczy", "workspace.modal.title": "Utwórz nowy obszar roboczy", @@ -75,6 +80,8 @@ export const dict = { "error.reloadAmountMin": "Kwota doładowania musi wynosić co najmniej ${{amount}}", "error.reloadTriggerMin": "Próg salda musi wynosić co najmniej ${{amount}}", + "app.meta.description": "OpenCode - Otwartoźródłowy agent programistyczny.", + "home.title": "OpenCode | Open source'owy agent AI do kodowania", "temp.title": "opencode | Agent AI do kodowania zbudowany dla terminala", @@ -90,6 +97,8 @@ export const dict = { "temp.feature.models.afterLink": ", w tym modele lokalne", "temp.screenshot.caption": "OpenCode TUI z motywem tokyonight", "temp.screenshot.alt": "OpenCode TUI z motywem tokyonight", + "temp.logoLightAlt": "jasne logo opencode", + "temp.logoDarkAlt": "ciemne logo opencode", "home.banner.badge": "Nowość", "home.banner.text": "Aplikacja desktopowa dostępna w wersji beta", @@ -241,6 +250,24 @@ export const dict = { "Wszystkie modele Zen są hostowane w USA. Dostawcy stosują politykę zerowej retencji i nie wykorzystują Twoich danych do trenowania modeli, z", "zen.privacy.exceptionsLink": "następującymi wyjątkami", + "zen.api.error.rateLimitExceeded": "Przekroczono limit zapytań. Spróbuj ponownie później.", + "zen.api.error.modelNotSupported": "Model {{model}} nie jest obsługiwany", + "zen.api.error.modelFormatNotSupported": "Model {{model}} nie jest obsługiwany dla formatu {{format}}", + "zen.api.error.noProviderAvailable": "Brak dostępnego dostawcy", + "zen.api.error.providerNotSupported": "Dostawca {{provider}} nie jest obsługiwany", + "zen.api.error.missingApiKey": "Brak klucza API.", + "zen.api.error.invalidApiKey": "Nieprawidłowy klucz API.", + "zen.api.error.subscriptionQuotaExceeded": "Przekroczono limit subskrypcji. Spróbuj ponownie za {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Przekroczono limit subskrypcji. Możesz kontynuować korzystanie z darmowych modeli.", + "zen.api.error.noPaymentMethod": "Brak metody płatności. Dodaj metodę płatności tutaj: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Niewystarczające saldo. Zarządzaj swoimi płatnościami tutaj: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Twoja przestrzeń robocza osiągnęła miesięczny limit wydatków w wysokości ${{amount}}. Zarządzaj swoimi limitami tutaj: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Osiągnąłeś swój miesięczny limit wydatków w wysokości ${{amount}}. Zarządzaj swoimi limitami tutaj: {{membersUrl}}", + "zen.api.error.modelDisabled": "Model jest wyłączony", + "black.meta.title": "OpenCode Black | Dostęp do najlepszych na świecie modeli kodujących", "black.meta.description": "Uzyskaj dostęp do Claude, GPT, Gemini i innych dzięki planom subskrypcji OpenCode Black.", "black.hero.title": "Dostęp do najlepszych na świecie modeli kodujących", @@ -450,6 +477,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Zaktualizuj metodę płatności i spróbuj ponownie.", "workspace.reload.retrying": "Ponawianie...", "workspace.reload.retry": "Spróbuj ponownie", + "workspace.reload.error.paymentFailed": "Płatność nie powiodła się.", "workspace.payments.title": "Historia płatności", "workspace.payments.subtitle": "Ostatnie transakcje płatnicze.", @@ -570,6 +598,10 @@ export const dict = { "enterprise.form.send": "Wyślij", "enterprise.form.sending": "Wysyłanie...", "enterprise.form.success": "Wiadomość wysłana, skontaktujemy się wkrótce.", + "enterprise.form.success.submitted": "Formularz został pomyślnie wysłany.", + "enterprise.form.error.allFieldsRequired": "Wszystkie pola są wymagane.", + "enterprise.form.error.invalidEmailFormat": "Nieprawidłowy format adresu e-mail.", + "enterprise.form.error.internalServer": "Wewnętrzny błąd serwera.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Czym jest OpenCode Enterprise?", "enterprise.faq.a1": @@ -602,6 +634,7 @@ export const dict = { "bench.list.table.agent": "Agent", "bench.list.table.model": "Model", "bench.list.table.score": "Wynik", + "bench.submission.error.allFieldsRequired": "Wszystkie pola są wymagane.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Nie znaleziono zadania", diff --git a/packages/console/app/src/i18n/ru.ts b/packages/console/app/src/i18n/ru.ts index 21b89dc94e..d0db17d29a 100644 --- a/packages/console/app/src/i18n/ru.ts +++ b/packages/console/app/src/i18n/ru.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Главная", "nav.openMenu": "Открыть меню", "nav.getStartedFree": "Начать бесплатно", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Скопировать логотип как SVG", "nav.context.copyWordmark": "Скопировать название как SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Документация", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "светлый логотип opencode", + "notFound.logoDarkAlt": "темный логотип opencode", "user.logout": "Выйти", + "auth.callback.error.codeMissing": "Код авторизации не найден.", + "workspace.select": "Выбрать рабочее пространство", "workspace.createNew": "+ Создать рабочее пространство", "workspace.modal.title": "Создать рабочее пространство", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "Сумма пополнения должна быть не менее ${{amount}}", "error.reloadTriggerMin": "Порог баланса должен быть не менее ${{amount}}", + "app.meta.description": "OpenCode - AI-агент с открытым кодом для программирования.", + "home.title": "OpenCode | AI-агент с открытым кодом для программирования", "temp.title": "opencode | AI-агент для программирования в терминале", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ", включая локальные модели", "temp.screenshot.caption": "OpenCode TUI с темой tokyonight", "temp.screenshot.alt": "OpenCode TUI с темой tokyonight", + "temp.logoLightAlt": "светлый логотип opencode", + "temp.logoDarkAlt": "темный логотип opencode", "home.banner.badge": "Новое", "home.banner.text": "Доступно десктопное приложение (бета)", @@ -244,6 +253,24 @@ export const dict = { "Все модели Zen размещены в США. Провайдеры следуют политике нулевого хранения и не используют ваши данные для обучения моделей, за", "zen.privacy.exceptionsLink": "следующими исключениями", + "zen.api.error.rateLimitExceeded": "Превышен лимит запросов. Пожалуйста, попробуйте позже.", + "zen.api.error.modelNotSupported": "Модель {{model}} не поддерживается", + "zen.api.error.modelFormatNotSupported": "Модель {{model}} не поддерживается для формата {{format}}", + "zen.api.error.noProviderAvailable": "Нет доступных провайдеров", + "zen.api.error.providerNotSupported": "Провайдер {{provider}} не поддерживается", + "zen.api.error.missingApiKey": "Отсутствует API ключ.", + "zen.api.error.invalidApiKey": "Неверный API ключ.", + "zen.api.error.subscriptionQuotaExceeded": "Квота подписки превышена. Повторите попытку через {{retryIn}}.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Квота подписки превышена. Вы можете продолжить использовать бесплатные модели.", + "zen.api.error.noPaymentMethod": "Нет способа оплаты. Добавьте способ оплаты здесь: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Недостаточно средств. Управляйте оплатой здесь: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Ваше рабочее пространство достигло ежемесячного лимита расходов в ${{amount}}. Управляйте лимитами здесь: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Вы достигли ежемесячного лимита расходов в ${{amount}}. Управляйте лимитами здесь: {{membersUrl}}", + "zen.api.error.modelDisabled": "Модель отключена", + "black.meta.title": "OpenCode Black | Доступ к лучшим моделям для кодинга в мире", "black.meta.description": "Получите доступ к Claude, GPT, Gemini и другим моделям с подпиской OpenCode Black.", "black.hero.title": "Доступ к лучшим моделям для кодинга в мире", @@ -455,6 +482,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Пожалуйста, обновите способ оплаты и попробуйте снова.", "workspace.reload.retrying": "Повторная попытка...", "workspace.reload.retry": "Повторить", + "workspace.reload.error.paymentFailed": "Ошибка оплаты.", "workspace.payments.title": "История платежей", "workspace.payments.subtitle": "Недавние транзакции.", @@ -574,6 +602,10 @@ export const dict = { "enterprise.form.send": "Отправить", "enterprise.form.sending": "Отправка...", "enterprise.form.success": "Сообщение отправлено, мы скоро свяжемся с вами.", + "enterprise.form.success.submitted": "Форма успешно отправлена.", + "enterprise.form.error.allFieldsRequired": "Все поля обязательны.", + "enterprise.form.error.invalidEmailFormat": "Неверный формат email.", + "enterprise.form.error.internalServer": "Внутренняя ошибка сервера.", "enterprise.faq.title": "FAQ", "enterprise.faq.q1": "Что такое OpenCode Enterprise?", "enterprise.faq.a1": @@ -606,6 +638,7 @@ export const dict = { "bench.list.table.agent": "Агент", "bench.list.table.model": "Модель", "bench.list.table.score": "Оценка", + "bench.submission.error.allFieldsRequired": "Все поля обязательны.", "bench.detail.title": "Бенчмарк - {{task}}", "bench.detail.notFound": "Задача не найдена", diff --git a/packages/console/app/src/i18n/th.ts b/packages/console/app/src/i18n/th.ts index 0646483544..129b789c97 100644 --- a/packages/console/app/src/i18n/th.ts +++ b/packages/console/app/src/i18n/th.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "หน้าหลัก", "nav.openMenu": "เปิดเมนู", "nav.getStartedFree": "เริ่มต้นฟรี", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "คัดลอกโลโก้เป็น SVG", "nav.context.copyWordmark": "คัดลอกตัวอักษรแบรนด์เป็น SVG", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "เอกสาร", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "โลโก้ opencode แบบสว่าง", + "notFound.logoDarkAlt": "โลโก้ opencode แบบมืด", "user.logout": "ออกจากระบบ", + "auth.callback.error.codeMissing": "ไม่พบ authorization code", + "workspace.select": "เลือก Workspace", "workspace.createNew": "+ สร้าง Workspace ใหม่", "workspace.modal.title": "สร้าง Workspace ใหม่", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "จำนวนเงินที่โหลดซ้ำต้องมีอย่างน้อย ${{amount}}", "error.reloadTriggerMin": "ยอดคงเหลือที่กระตุ้นต้องมีอย่างน้อย ${{amount}}", + "app.meta.description": "OpenCode - เอเจนต์เขียนโค้ดแบบโอเพนซอร์ส", + "home.title": "OpenCode | เอเจนต์เขียนโค้ดด้วย AI แบบโอเพนซอร์ส", "temp.title": "OpenCode | เอเจนต์เขียนโค้ด AI ที่สร้างมาเพื่อเทอร์มินัล", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": "รวมถึงโมเดล Local", "temp.screenshot.caption": "OpenCode TUI พร้อมธีม tokyonight", "temp.screenshot.alt": "OpenCode TUI พร้อมธีม tokyonight", + "temp.logoLightAlt": "โลโก้ opencode แบบสว่าง", + "temp.logoDarkAlt": "โลโก้ opencode แบบมืด", "home.banner.badge": "ใหม่", "home.banner.text": "แอปเดสก์ท็อปพร้อมใช้งานในเวอร์ชันเบต้า", @@ -239,6 +248,24 @@ export const dict = { "โมเดล Zen ทั้งหมดโฮสต์ในสหรัฐอเมริกา ผู้ให้บริการปฏิบัติตามนโยบายไม่เก็บรักษาข้อมูล (zero-retention policy) และไม่ใช้ข้อมูลของคุณสำหรับการฝึกโมเดล โดยมี", "zen.privacy.exceptionsLink": "ข้อยกเว้นดังนี้", + "zen.api.error.rateLimitExceeded": "เกินขีดจำกัดอัตราการใช้งาน กรุณาลองใหม่ในภายหลัง", + "zen.api.error.modelNotSupported": "ไม่รองรับโมเดล {{model}}", + "zen.api.error.modelFormatNotSupported": "ไม่รองรับโมเดล {{model}} สำหรับรูปแบบ {{format}}", + "zen.api.error.noProviderAvailable": "ไม่มีผู้ให้บริการที่พร้อมใช้งาน", + "zen.api.error.providerNotSupported": "ไม่รองรับผู้ให้บริการ {{provider}}", + "zen.api.error.missingApiKey": "ไม่มี API key", + "zen.api.error.invalidApiKey": "API key ไม่ถูกต้อง", + "zen.api.error.subscriptionQuotaExceeded": "โควต้าการสมัครสมาชิกเกินขีดจำกัด ลองใหม่ในอีก {{retryIn}}", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "โควต้าการสมัครสมาชิกเกินขีดจำกัด คุณสามารถดำเนินการต่อโดยใช้โมเดลฟรี", + "zen.api.error.noPaymentMethod": "ไม่มีวิธีการชำระเงิน เพิ่มวิธีการชำระเงินที่นี่: {{billingUrl}}", + "zen.api.error.insufficientBalance": "ยอดเงินคงเหลือไม่เพียงพอ จัดการการเรียกเก็บเงินของคุณที่นี่: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Workspace ของคุณถึงขีดจำกัดการใช้จ่ายรายเดือนที่ ${{amount}} แล้ว จัดการขีดจำกัดของคุณที่นี่: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "คุณถึงขีดจำกัดการใช้จ่ายรายเดือนที่ ${{amount}} แล้ว จัดการขีดจำกัดของคุณที่นี่: {{membersUrl}}", + "zen.api.error.modelDisabled": "โมเดลถูกปิดใช้งาน", + "black.meta.title": "OpenCode Black | เข้าถึงโมเดลเขียนโค้ดที่ดีที่สุดในโลก", "black.meta.description": "เข้าถึง Claude, GPT, Gemini และอื่นๆ ด้วยแผนสมาชิก OpenCode Black", "black.hero.title": "เข้าถึงโมเดลเขียนโค้ดที่ดีที่สุดในโลก", @@ -448,6 +475,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "โปรดอัปเดตวิธีการชำระเงินของคุณแล้วลองอีกครั้ง", "workspace.reload.retrying": "กำลังลองอีกครั้ง...", "workspace.reload.retry": "ลองอีกครั้ง", + "workspace.reload.error.paymentFailed": "การชำระเงินล้มเหลว", "workspace.payments.title": "ประวัติการชำระเงิน", "workspace.payments.subtitle": "รายการธุรกรรมการชำระเงินล่าสุด", @@ -566,6 +594,10 @@ export const dict = { "enterprise.form.send": "ส่ง", "enterprise.form.sending": "กำลังส่ง...", "enterprise.form.success": "ส่งข้อความแล้ว เราจะติดต่อกลับเร็วๆ นี้", + "enterprise.form.success.submitted": "ส่งแบบฟอร์มสำเร็จแล้ว", + "enterprise.form.error.allFieldsRequired": "จำเป็นต้องกรอกทุกช่อง", + "enterprise.form.error.invalidEmailFormat": "รูปแบบอีเมลไม่ถูกต้อง", + "enterprise.form.error.internalServer": "เกิดข้อผิดพลาดภายในเซิร์ฟเวอร์", "enterprise.faq.title": "คำถามที่พบบ่อย", "enterprise.faq.q1": "OpenCode Enterprise คืออะไร?", "enterprise.faq.a1": @@ -598,6 +630,7 @@ export const dict = { "bench.list.table.agent": "เอเจนต์", "bench.list.table.model": "โมเดล", "bench.list.table.score": "คะแนน", + "bench.submission.error.allFieldsRequired": "จำเป็นต้องกรอกทุกช่อง", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "ไม่พบงาน", diff --git a/packages/console/app/src/i18n/tr.ts b/packages/console/app/src/i18n/tr.ts index d94dd15d0d..bd7a3042d7 100644 --- a/packages/console/app/src/i18n/tr.ts +++ b/packages/console/app/src/i18n/tr.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "Ana sayfa", "nav.openMenu": "Menüyü aç", "nav.getStartedFree": "Ücretsiz başla", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "Logoyu SVG olarak kopyala", "nav.context.copyWordmark": "Wordmark'ı SVG olarak kopyala", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "Dokümantasyon", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode açık logo", + "notFound.logoDarkAlt": "opencode koyu logo", "user.logout": "Çıkış", + "auth.callback.error.codeMissing": "Yetkilendirme kodu bulunamadı.", + "workspace.select": "Çalışma alanı seç", "workspace.createNew": "+ Yeni çalışma alanı oluştur", "workspace.modal.title": "Yeni çalışma alanı oluştur", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "Yükleme tutarı en az ${{amount}} olmalıdır", "error.reloadTriggerMin": "Bakiye tetikleyicisi en az ${{amount}} olmalıdır", + "app.meta.description": "OpenCode - Açık kaynaklı kodlama ajanı.", + "home.title": "OpenCode | Açık kaynaklı yapay zeka kodlama ajanı", "temp.title": "opencode | Terminal için geliştirilmiş yapay zeka kodlama ajanı", @@ -91,9 +98,11 @@ export const dict = { "temp.feature.models.afterLink": " üzerinden destekler", "temp.screenshot.caption": "opencode TUI ve tokyonight teması", "temp.screenshot.alt": "tokyonight temalı opencode TUI", + "temp.logoLightAlt": "opencode açık logo", + "temp.logoDarkAlt": "opencode koyu logo", "home.banner.badge": "Yeni", - "home.banner.text": "Masaüstü uygulaması beta olarak kullanılabilir", + "home.banner.text": "Masaüstü uygulaması beta olarak mevcut", "home.banner.platforms": "macOS, Windows ve Linux'ta", "home.banner.downloadNow": "Şimdi indir", "home.banner.downloadBetaNow": "Masaüstü betayı şimdi indir", @@ -130,7 +139,7 @@ export const dict = { "home.growth.contributors": "Katılımcılar", "home.growth.monthlyDevs": "Aylık Geliştiriciler", - "home.privacy.title": "Önce gizlilik için tasarlandı", + "home.privacy.title": "Gizlilik öncelikli tasarlandı", "home.privacy.body": "OpenCode kodunuzu veya bağlam verilerinizi saklamaz; bu sayede gizliliğe duyarlı ortamlarda çalışabilir.", "home.privacy.learnMore": "Hakkında daha fazla bilgi:", @@ -148,12 +157,12 @@ export const dict = { "home.faq.a3.p2.afterZen": " hesabı oluşturabilirsiniz.", "home.faq.a3.p3": "Zen'i öneriyoruz, ancak OpenCode OpenAI, Anthropic, xAI gibi popüler sağlayıcılarla da çalışır.", "home.faq.a3.p4.beforeLocal": "Hatta", - "home.faq.a3.p4.localLink": "yerel modellerinizi", + "home.faq.a3.p4.localLink": "yerel modellerinizi bağlayabilirsiniz", "home.faq.q4": "Mevcut AI aboneliklerimi OpenCode ile kullanabilir miyim?", "home.faq.a4.p1": "Evet. OpenCode tüm büyük sağlayıcıların aboneliklerini destekler. Claude Pro/Max, ChatGPT Plus/Pro veya GitHub Copilot kullanabilirsiniz.", "home.faq.q5": "OpenCode'u sadece terminalde mi kullanabilirim?", - "home.faq.a5.beforeDesktop": "Artık hayır! OpenCode şimdi", + "home.faq.a5.beforeDesktop": "Artık hayır! OpenCode artık sizin bu cihazlarınıza", "home.faq.a5.desktop": "masaüstü", "home.faq.a5.and": "ve", "home.faq.a5.web": "web", @@ -169,10 +178,10 @@ export const dict = { "home.faq.a7.p2.shareLink": "paylaşım sayfaları", "home.faq.q8": "OpenCode açık kaynak mı?", "home.faq.a8.p1": "Evet, OpenCode tamamen açık kaynaktır. Kaynak kodu", - "home.faq.a8.p2": "altında", + "home.faq.a8.p2": "'da", "home.faq.a8.mitLicense": "MIT Lisansı", "home.faq.a8.p3": - ", yani herkes kullanabilir, değiştirebilir veya geliştirmeye katkıda bulunabilir. Topluluktan herkes issue açabilir, pull request gönderebilir ve işlevselliği genişletebilir.", + "altında herkese açıktır, yani herkes kullanabilir, değiştirebilir veya geliştirmeye katkıda bulunabilir. Topluluktan herkes issue açabilir, pull request gönderebilir ve işlevselliği genişletebilir.", "home.zenCta.title": "Kodlama ajanları için güvenilir, optimize modeller", "home.zenCta.body": @@ -242,6 +251,24 @@ export const dict = { "Tüm Zen modelleri ABD'de barındırılmaktadır. Sağlayıcılar sıfır saklama politikası izler ve verilerinizi model eğitimi için kullanmaz; şu", "zen.privacy.exceptionsLink": "aşağıdaki istisnalar", + "zen.api.error.rateLimitExceeded": "İstek limiti aşıldı. Lütfen daha sonra tekrar deneyin.", + "zen.api.error.modelNotSupported": "{{model}} modeli desteklenmiyor", + "zen.api.error.modelFormatNotSupported": "{{model}} modeli {{format}} formatı için desteklenmiyor", + "zen.api.error.noProviderAvailable": "Kullanılabilir sağlayıcı yok", + "zen.api.error.providerNotSupported": "{{provider}} sağlayıcısı desteklenmiyor", + "zen.api.error.missingApiKey": "API anahtarı eksik.", + "zen.api.error.invalidApiKey": "Geçersiz API anahtarı.", + "zen.api.error.subscriptionQuotaExceeded": "Abonelik kotası aşıldı. {{retryIn}} içinde tekrar deneyin.", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": + "Abonelik kotası aşıldı. Ücretsiz modelleri kullanmaya devam edebilirsiniz.", + "zen.api.error.noPaymentMethod": "Ödeme yöntemi bulunamadı. Buradan bir ödeme yöntemi ekleyin: {{billingUrl}}", + "zen.api.error.insufficientBalance": "Yetersiz bakiye. Faturalandırmanızı buradan yönetin: {{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "Çalışma alanınız aylık ${{amount}} harcama limitine ulaştı. Limitlerinizi buradan yönetin: {{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": + "Aylık ${{amount}} harcama limitinize ulaştınız. Limitlerinizi buradan yönetin: {{membersUrl}}", + "zen.api.error.modelDisabled": "Model devre dışı", + "black.meta.title": "OpenCode Black | Dünyanın en iyi kodlama modellerine erişin", "black.meta.description": "OpenCode Black abonelik planlarıyla Claude, GPT, Gemini ve daha fazlasına erişin.", "black.hero.title": "Dünyanın en iyi kodlama modellerine erişin", @@ -451,6 +478,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "Lütfen ödeme yönteminizi güncelleyin ve tekrar deneyin.", "workspace.reload.retrying": "Yeniden deneniyor...", "workspace.reload.retry": "Yeniden dene", + "workspace.reload.error.paymentFailed": "Ödeme başarısız.", "workspace.payments.title": "Ödeme Geçmişi", "workspace.payments.subtitle": "Son ödeme işlemleri.", @@ -571,6 +599,10 @@ export const dict = { "enterprise.form.send": "Gönder", "enterprise.form.sending": "Gönderiliyor...", "enterprise.form.success": "Mesaj gönderildi, yakında size dönüş yapacağız.", + "enterprise.form.success.submitted": "Form başarıyla gönderildi.", + "enterprise.form.error.allFieldsRequired": "Tüm alanlar gereklidir.", + "enterprise.form.error.invalidEmailFormat": "Geçersiz e-posta formatı.", + "enterprise.form.error.internalServer": "İç sunucu hatası.", "enterprise.faq.title": "SSS", "enterprise.faq.q1": "OpenCode Enterprise nedir?", "enterprise.faq.a1": @@ -603,6 +635,7 @@ export const dict = { "bench.list.table.agent": "Ajan", "bench.list.table.model": "Model", "bench.list.table.score": "Puan", + "bench.submission.error.allFieldsRequired": "Tüm alanlar gereklidir.", "bench.detail.title": "Benchmark - {{task}}", "bench.detail.notFound": "Görev bulunamadı", diff --git a/packages/console/app/src/i18n/zh.ts b/packages/console/app/src/i18n/zh.ts index bf21073ce1..74c8de4344 100644 --- a/packages/console/app/src/i18n/zh.ts +++ b/packages/console/app/src/i18n/zh.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "首页", "nav.openMenu": "打开菜单", "nav.getStartedFree": "免费开始", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "复制 Logo (SVG)", "nav.context.copyWordmark": "复制商标 (SVG)", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "文档", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode logo 亮色", + "notFound.logoDarkAlt": "opencode logo 暗色", "user.logout": "退出登录", + "auth.callback.error.codeMissing": "未找到授权码。", + "workspace.select": "选择工作区", "workspace.createNew": "+ 新建工作区", "workspace.modal.title": "新建工作区", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "充值金额必须至少为 ${{amount}}", "error.reloadTriggerMin": "余额触发阈值必须至少为 ${{amount}}", + "app.meta.description": "OpenCode - 开源编程代理。", + "home.title": "OpenCode | 开源 AI 编程代理", "temp.title": "OpenCode | 专为终端打造的 AI 编程代理", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": ",包括本地模型", "temp.screenshot.caption": "使用 Tokyonight 主题的 OpenCode TUI", "temp.screenshot.alt": "使用 Tokyonight 主题的 OpenCode TUI", + "temp.logoLightAlt": "opencode logo 亮色", + "temp.logoDarkAlt": "opencode logo 暗色", "home.banner.badge": "新", "home.banner.text": "桌面应用 Beta 版现已推出", @@ -229,6 +238,22 @@ export const dict = { "zen.privacy.beforeExceptions": "所有 Zen 模型均托管在美国。提供商遵循零留存政策,不使用您的数据进行模型训练,", "zen.privacy.exceptionsLink": "以下例外情况除外", + "zen.api.error.rateLimitExceeded": "超出速率限制。请稍后重试。", + "zen.api.error.modelNotSupported": "不支持模型 {{model}}", + "zen.api.error.modelFormatNotSupported": "格式 {{format}} 不支持模型 {{model}}", + "zen.api.error.noProviderAvailable": "没有可用的提供商", + "zen.api.error.providerNotSupported": "不支持提供商 {{provider}}", + "zen.api.error.missingApiKey": "缺少 API 密钥。", + "zen.api.error.invalidApiKey": "无效的 API 密钥。", + "zen.api.error.subscriptionQuotaExceeded": "超出订阅配额。请在 {{retryIn}} 后重试。", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": "超出订阅配额。您可以继续使用免费模型。", + "zen.api.error.noPaymentMethod": "没有付款方式。请在此处添加付款方式:{{billingUrl}}", + "zen.api.error.insufficientBalance": "余额不足。请在此处管理您的计费:{{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "您的工作区已达到每月支出限额 ${{amount}}。请在此处管理您的限额:{{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": "您已达到每月支出限额 ${{amount}}。请在此处管理您的限额:{{membersUrl}}", + "zen.api.error.modelDisabled": "模型已禁用", + "black.meta.title": "OpenCode Black | 访问全球顶尖编程模型", "black.meta.description": "通过 OpenCode Black 订阅计划使用 Claude, GPT, Gemini 等模型。", "black.hero.title": "访问全球顶尖编程模型", @@ -436,6 +461,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "请更新您的付款方式并重试。", "workspace.reload.retrying": "正在重试...", "workspace.reload.retry": "重试", + "workspace.reload.error.paymentFailed": "支付失败。", "workspace.payments.title": "支付历史", "workspace.payments.subtitle": "近期支付交易。", @@ -552,6 +578,10 @@ export const dict = { "enterprise.form.send": "发送", "enterprise.form.sending": "正在发送...", "enterprise.form.success": "消息已发送,我们会尽快与您联系。", + "enterprise.form.success.submitted": "表单提交成功。", + "enterprise.form.error.allFieldsRequired": "所有字段均为必填项。", + "enterprise.form.error.invalidEmailFormat": "邮箱格式无效。", + "enterprise.form.error.internalServer": "内部服务器错误。", "enterprise.faq.title": "常见问题", "enterprise.faq.q1": "什么是 OpenCode 企业版?", "enterprise.faq.a1": @@ -584,6 +614,7 @@ export const dict = { "bench.list.table.agent": "代理", "bench.list.table.model": "模型", "bench.list.table.score": "分数", + "bench.submission.error.allFieldsRequired": "所有字段均为必填项。", "bench.detail.title": "基准测试 - {{task}}", "bench.detail.notFound": "未找到任务", diff --git a/packages/console/app/src/i18n/zht.ts b/packages/console/app/src/i18n/zht.ts index 8ac69596cb..db06860eed 100644 --- a/packages/console/app/src/i18n/zht.ts +++ b/packages/console/app/src/i18n/zht.ts @@ -15,6 +15,7 @@ export const dict = { "nav.home": "首頁", "nav.openMenu": "開啟選單", "nav.getStartedFree": "免費開始使用", + "nav.logoAlt": "OpenCode", "nav.context.copyLogo": "複製標誌(SVG)", "nav.context.copyWordmark": "複製字標(SVG)", @@ -42,9 +43,13 @@ export const dict = { "notFound.docs": "文件", "notFound.github": "GitHub", "notFound.discord": "Discord", + "notFound.logoLightAlt": "opencode 淺色標誌", + "notFound.logoDarkAlt": "opencode 深色標誌", "user.logout": "登出", + "auth.callback.error.codeMissing": "找不到授權碼。", + "workspace.select": "選取工作區", "workspace.createNew": "+ 建立新工作區", "workspace.modal.title": "建立新工作區", @@ -76,6 +81,8 @@ export const dict = { "error.reloadAmountMin": "儲值金額必須至少為 ${{amount}}", "error.reloadTriggerMin": "餘額觸發門檻必須至少為 ${{amount}}", + "app.meta.description": "OpenCode - 開源編碼代理。", + "home.title": "OpenCode | 開源 AI 編碼代理", "temp.title": "OpenCode | 專為終端打造的 AI 編碼代理", @@ -91,6 +98,8 @@ export const dict = { "temp.feature.models.afterLink": "支援 75+ 家 LLM 供應商,包括本地模型", "temp.screenshot.caption": "使用 tokyonight 主題的 OpenCode TUI", "temp.screenshot.alt": "使用 tokyonight 主題的 OpenCode TUI", + "temp.logoLightAlt": "opencode 淺色標誌", + "temp.logoDarkAlt": "opencode 深色標誌", "home.banner.badge": "新", "home.banner.text": "桌面應用已推出 Beta", @@ -229,6 +238,22 @@ export const dict = { "zen.privacy.beforeExceptions": "所有 Zen 模型均在美國託管。供應商遵循零留存政策,不會將你的資料用於模型訓練,並且有", "zen.privacy.exceptionsLink": "以下例外情況", + "zen.api.error.rateLimitExceeded": "超出頻率限制。請稍後再試。", + "zen.api.error.modelNotSupported": "不支援模型 {{model}}", + "zen.api.error.modelFormatNotSupported": "模型 {{model}} 不支援格式 {{format}}", + "zen.api.error.noProviderAvailable": "無可用的供應商", + "zen.api.error.providerNotSupported": "不支援供應商 {{provider}}", + "zen.api.error.missingApiKey": "缺少 API 金鑰。", + "zen.api.error.invalidApiKey": "無效的 API 金鑰。", + "zen.api.error.subscriptionQuotaExceeded": "超出訂閱配額。請在 {{retryIn}} 後重試。", + "zen.api.error.subscriptionQuotaExceededUseFreeModels": "超出訂閱配額。你可以繼續使用免費模型。", + "zen.api.error.noPaymentMethod": "無付款方式。請在此處新增付款方式:{{billingUrl}}", + "zen.api.error.insufficientBalance": "餘額不足。請在此處管理你的帳務:{{billingUrl}}", + "zen.api.error.workspaceMonthlyLimitReached": + "你的工作區已達到每月支出限額 ${{amount}}。請在此處管理你的限額:{{billingUrl}}", + "zen.api.error.userMonthlyLimitReached": "你已達到每月支出限額 ${{amount}}。請在此處管理你的限額:{{membersUrl}}", + "zen.api.error.modelDisabled": "模型已停用", + "black.meta.title": "OpenCode Black | 存取全球最佳編碼模型", "black.meta.description": "透過 OpenCode Black 訂閱方案存取 Claude、GPT、Gemini 等模型。", "black.hero.title": "存取全球最佳編碼模型", @@ -436,6 +461,7 @@ export const dict = { "workspace.reload.updatePaymentMethod": "請更新你的付款方式並重試。", "workspace.reload.retrying": "重試中...", "workspace.reload.retry": "重試", + "workspace.reload.error.paymentFailed": "付款失敗。", "workspace.payments.title": "付款紀錄", "workspace.payments.subtitle": "最近的付款交易。", @@ -551,6 +577,10 @@ export const dict = { "enterprise.form.send": "傳送", "enterprise.form.sending": "傳送中...", "enterprise.form.success": "訊息已傳送,我們會盡快與你聯絡。", + "enterprise.form.success.submitted": "表單已成功送出。", + "enterprise.form.error.allFieldsRequired": "所有欄位均為必填。", + "enterprise.form.error.invalidEmailFormat": "無效的電子郵件格式。", + "enterprise.form.error.internalServer": "內部伺服器錯誤。", "enterprise.faq.title": "常見問題", "enterprise.faq.q1": "什麼是 OpenCode Enterprise?", "enterprise.faq.a1": @@ -583,6 +613,7 @@ export const dict = { "bench.list.table.agent": "代理", "bench.list.table.model": "模型", "bench.list.table.score": "分數", + "bench.submission.error.allFieldsRequired": "所有欄位均為必填。", "bench.detail.title": "評測 - {{task}}", "bench.detail.notFound": "找不到任務", diff --git a/packages/console/app/src/lib/form-error.ts b/packages/console/app/src/lib/form-error.ts index 1f6e2ea1e6..d643a98f14 100644 --- a/packages/console/app/src/lib/form-error.ts +++ b/packages/console/app/src/lib/form-error.ts @@ -48,6 +48,9 @@ const map = { "Provider is required": "error.providerRequired", "API key is required": "error.apiKeyRequired", "Model is required": "error.modelRequired", + "workspace.reload.error.paymentFailed": "workspace.reload.error.paymentFailed", + "Payment failed": "workspace.reload.error.paymentFailed", + "Payment failed.": "workspace.reload.error.paymentFailed", } as const satisfies Record export function formErrorReloadAmountMin(amount: number) { diff --git a/packages/console/app/src/routes/[...404].tsx b/packages/console/app/src/routes/[...404].tsx index 414491f9d1..e20ec36fd6 100644 --- a/packages/console/app/src/routes/[...404].tsx +++ b/packages/console/app/src/routes/[...404].tsx @@ -16,8 +16,8 @@ export default function NotFound() {
- opencode logo light - opencode logo dark + {i18n.t("notFound.logoLightAlt")} + {i18n.t("notFound.logoDarkAlt")}

{i18n.t("notFound.heading")}

diff --git a/packages/console/app/src/routes/api/enterprise.ts b/packages/console/app/src/routes/api/enterprise.ts index 6776a7b3c7..27e2dc4938 100644 --- a/packages/console/app/src/routes/api/enterprise.ts +++ b/packages/console/app/src/routes/api/enterprise.ts @@ -1,5 +1,7 @@ import type { APIEvent } from "@solidjs/start/server" import { AWS } from "@opencode-ai/console-core/aws.js" +import { i18n } from "~/i18n" +import { localeFromRequest } from "~/lib/language" interface EnterpriseFormData { name: string @@ -9,18 +11,19 @@ interface EnterpriseFormData { } export async function POST(event: APIEvent) { + const dict = i18n(localeFromRequest(event.request)) try { const body = (await event.request.json()) as EnterpriseFormData // Validate required fields if (!body.name || !body.role || !body.email || !body.message) { - return Response.json({ error: "All fields are required" }, { status: 400 }) + return Response.json({ error: dict["enterprise.form.error.allFieldsRequired"] }, { status: 400 }) } // Validate email format const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ if (!emailRegex.test(body.email)) { - return Response.json({ error: "Invalid email format" }, { status: 400 }) + return Response.json({ error: dict["enterprise.form.error.invalidEmailFormat"] }, { status: 400 }) } // Create email content @@ -39,9 +42,9 @@ ${body.email}`.trim() replyTo: body.email, }) - return Response.json({ success: true, message: "Form submitted successfully" }, { status: 200 }) + return Response.json({ success: true, message: dict["enterprise.form.success.submitted"] }, { status: 200 }) } catch (error) { console.error("Error processing enterprise form:", error) - return Response.json({ error: "Internal server error" }, { status: 500 }) + return Response.json({ error: dict["enterprise.form.error.internalServer"] }, { status: 500 }) } } diff --git a/packages/console/app/src/routes/auth/[...callback].ts b/packages/console/app/src/routes/auth/[...callback].ts index 664f6cc6d1..00bb89406f 100644 --- a/packages/console/app/src/routes/auth/[...callback].ts +++ b/packages/console/app/src/routes/auth/[...callback].ts @@ -2,15 +2,17 @@ import { redirect } from "@solidjs/router" import type { APIEvent } from "@solidjs/start/server" import { AuthClient } from "~/context/auth" import { useAuthSession } from "~/context/auth" +import { i18n } from "~/i18n" import { localeFromRequest, route } from "~/lib/language" export async function GET(input: APIEvent) { const url = new URL(input.request.url) const locale = localeFromRequest(input.request) + const dict = i18n(locale) try { const code = url.searchParams.get("code") - if (!code) throw new Error("No code found") + if (!code) throw new Error(dict["auth.callback.error.codeMissing"]) const result = await AuthClient.exchange(code, `${url.origin}${url.pathname}`) if (result.err) throw new Error(result.err.message) const decoded = AuthClient.decode(result.tokens.access, {} as any) diff --git a/packages/console/app/src/routes/bench/submission.ts b/packages/console/app/src/routes/bench/submission.ts index 94639439b1..969ff16593 100644 --- a/packages/console/app/src/routes/bench/submission.ts +++ b/packages/console/app/src/routes/bench/submission.ts @@ -2,6 +2,8 @@ import type { APIEvent } from "@solidjs/start/server" import { Database } from "@opencode-ai/console-core/drizzle/index.js" import { BenchmarkTable } from "@opencode-ai/console-core/schema/benchmark.sql.js" import { Identifier } from "@opencode-ai/console-core/identifier.js" +import { i18n } from "~/i18n" +import { localeFromRequest } from "~/lib/language" interface SubmissionBody { model: string @@ -10,10 +12,11 @@ interface SubmissionBody { } export async function POST(event: APIEvent) { + const dict = i18n(localeFromRequest(event.request)) const body = (await event.request.json()) as SubmissionBody if (!body.model || !body.agent || !body.result) { - return Response.json({ error: "All fields are required" }, { status: 400 }) + return Response.json({ error: dict["bench.submission.error.allFieldsRequired"] }, { status: 400 }) } await Database.use((tx) => diff --git a/packages/console/app/src/routes/brand/index.tsx b/packages/console/app/src/routes/brand/index.tsx index 9140462c79..af89f49851 100644 --- a/packages/console/app/src/routes/brand/index.tsx +++ b/packages/console/app/src/routes/brand/index.tsx @@ -33,6 +33,7 @@ const brandAssets = "/opencode-brand-assets.zip" export default function Brand() { const i18n = useI18n() + const alt = i18n.t("brand.meta.description") const downloadFile = async (url: string, filename: string) => { try { const response = await fetch(url) @@ -88,7 +89,7 @@ export default function Brand() {
- OpenCode brand guidelines + {alt}
- OpenCode brand guidelines + {alt}
- OpenCode brand guidelines + {alt}
- OpenCode brand guidelines + {alt}
- OpenCode brand guidelines + {alt}
- OpenCode brand guidelines + {alt}
- OpenCode brand guidelines + {alt}
- OpenCode brand guidelines + {alt}
}> - {(preloaded) => ( -
- -
- )} - - - ) - }, -} diff --git a/packages/ui/src/components/diff.stories.tsx b/packages/ui/src/components/diff.stories.tsx deleted file mode 100644 index 03bf4a0e0f..0000000000 --- a/packages/ui/src/components/diff.stories.tsx +++ /dev/null @@ -1,96 +0,0 @@ -// @ts-nocheck -import * as mod from "./diff" -import { create } from "../storybook/scaffold" -import { diff } from "../storybook/fixtures" - -const docs = `### Overview -Render a code diff with OpenCode styling using the Pierre diff engine. - -Pair with \`DiffChanges\` for summary counts. -Use \`LineComment\` or external UI for annotation workflows. - -### API -- Required: \`before\` and \`after\` file contents (name + contents). -- Optional: \`diffStyle\` ("unified" | "split"), \`annotations\`, \`selectedLines\`, \`commentedLines\`. -- Optional interaction: \`enableLineSelection\`, \`onLineSelectionEnd\`. -- Passes through Pierre FileDiff options (see component source). - -### Variants and states -- Unified and split diff styles. -- Optional line selection + commented line highlighting. - -### Behavior -- Re-renders when \`before\`/\`after\` or diff options change. -- Line selection uses mouse drag/selection when enabled. - -### Accessibility -- TODO: confirm keyboard behavior from the Pierre diff engine. -- Provide surrounding labels or headings when used as a standalone view. - -### Theming/tokens -- Uses \`data-component="diff"\` and Pierre CSS variables from \`styleVariables\`. -- Colors derive from theme tokens (diff add/delete, background, text). - -` - -const story = create({ - title: "UI/Diff", - mod, - args: { - before: diff.before, - after: diff.after, - diffStyle: "unified", - }, -}) - -export default { - title: "UI/Diff", - id: "components-diff", - component: story.meta.component, - tags: ["autodocs"], - parameters: { - docs: { - description: { - component: docs, - }, - }, - }, - argTypes: { - diffStyle: { - control: "select", - options: ["unified", "split"], - }, - enableLineSelection: { - control: "boolean", - }, - }, -} - -export const Unified = story.Basic - -export const Split = { - args: { - diffStyle: "split", - }, -} - -export const Selectable = { - args: { - enableLineSelection: true, - }, -} - -export const SelectedLines = { - args: { - selectedLines: { start: 2, end: 4 }, - }, -} - -export const CommentedLines = { - args: { - commentedLines: [ - { start: 1, end: 1 }, - { start: 4, end: 4 }, - ], - }, -} diff --git a/packages/ui/src/components/message-part.css b/packages/ui/src/components/message-part.css index bea33ff54c..3eee45c75f 100644 --- a/packages/ui/src/components/message-part.css +++ b/packages/ui/src/components/message-part.css @@ -46,12 +46,18 @@ overflow: hidden; background: var(--surface-weak); border: 1px solid var(--border-weak-base); - transition: border-color 0.15s ease; + transition: + border-color 0.15s ease, + opacity 0.3s ease; &:hover { border-color: var(--border-strong-base); } + &[data-queued] { + opacity: 0.6; + } + &[data-type="image"] { width: 48px; height: 48px; @@ -101,6 +107,11 @@ border: 1px solid var(--border-weak-base); padding: 8px 12px; border-radius: 6px; + transition: opacity 0.3s ease; + + &[data-queued] { + opacity: 0.6; + } [data-highlight="file"] { color: var(--syntax-property); @@ -113,6 +124,14 @@ max-width: 100%; } + [data-slot="user-message-queued-indicator"] { + margin-top: 6px; + margin-right: 2px; + font-size: var(--font-size-small); + color: var(--text-weak); + user-select: none; + } + [data-slot="user-message-copy-wrapper"] { min-height: 24px; margin-top: 4px; @@ -149,6 +168,7 @@ align-items: center; justify-content: flex-end; overflow: hidden; + gap: 6px; } [data-slot="user-message-meta-tail"] { @@ -225,6 +245,33 @@ } } +[data-component="compaction-part"] { + width: 100%; + display: flex; + flex-direction: column; + align-items: stretch; + + [data-slot="compaction-part-divider"] { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 0; + width: 100%; + } + + [data-slot="compaction-part-line"] { + flex: 1 1 auto; + height: 1px; + background: var(--border-weak-base); + } + + [data-slot="compaction-part-label"] { + flex: 0 0 auto; + white-space: nowrap; + text-align: center; + } +} + [data-component="reasoning-part"] { width: 100%; color: var(--text-base); @@ -561,29 +608,8 @@ cursor: pointer; [data-slot="context-tool-group-title"] { - min-width: 0; - display: flex; - align-items: center; - gap: 8px; - font-family: var(--font-family-sans); - font-size: 14px; - font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); - color: var(--text-strong); - } - - [data-slot="context-tool-group-label"] { - flex-shrink: 0; - } - - [data-slot="context-tool-group-summary"] { flex-shrink: 1; min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-weight: var(--font-weight-regular); - color: var(--text-base); } [data-slot="collapsible-arrow"] { @@ -649,6 +675,7 @@ [data-component="reasoning-part"], [data-component="tool-error"], [data-component="tool-output"], +[data-component="bash-output"], [data-component="edit-content"], [data-component="write-content"], [data-component="todos"], diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx index 5c110ccd66..a97b386718 100644 --- a/packages/ui/src/components/message-part.tsx +++ b/packages/ui/src/components/message-part.tsx @@ -5,9 +5,11 @@ import { createSignal, For, Match, + onMount, Show, Switch, onCleanup, + Index, type JSX, } from "solid-js" import stripAnsi from "strip-ansi" @@ -47,6 +49,42 @@ import { checksum } from "@opencode-ai/util/encode" import { Tooltip } from "./tooltip" import { IconButton } from "./icon-button" import { TextShimmer } from "./text-shimmer" +import { AnimatedCountList } from "./tool-count-summary" +import { ToolStatusTitle } from "./tool-status-title" +import { animate } from "motion" + +function ShellSubmessage(props: { text: string; animate?: boolean }) { + let widthRef: HTMLSpanElement | undefined + let valueRef: HTMLSpanElement | undefined + + onMount(() => { + if (!props.animate) return + requestAnimationFrame(() => { + if (widthRef) { + animate(widthRef, { width: "auto" }, { type: "spring", visualDuration: 0.25, bounce: 0 }) + } + if (valueRef) { + animate(valueRef, { opacity: 1, filter: "blur(0px)" }, { duration: 0.32, ease: [0.16, 1, 0.3, 1] }) + } + }) + }) + + return ( + + + + + {props.text} + + + + + ) +} interface Diagnostic { range: { @@ -92,6 +130,7 @@ export interface MessageProps { parts: PartType[] showAssistantCopyPartID?: string | null interrupted?: boolean + queued?: boolean showReasoningSummaries?: boolean } @@ -250,6 +289,11 @@ export function getToolInfo(tool: string, input: any = {}): ToolInfo { icon: "bubble-5", title: i18n.t("ui.tool.questions"), } + case "skill": + return { + icon: "brain", + title: input.name || "skill", + } default: return { icon: "mcp", @@ -266,6 +310,102 @@ function list(value: T[] | undefined | null, fallback: T[]) { return fallback } +function same(a: readonly T[] | undefined, b: readonly T[] | undefined) { + if (a === b) return true + if (!a || !b) return false + if (a.length !== b.length) return false + return a.every((x, i) => x === b[i]) +} + +type PartRef = { + messageID: string + partID: string +} + +type PartGroup = + | { + key: string + type: "part" + ref: PartRef + } + | { + key: string + type: "context" + refs: PartRef[] + } + +function sameRef(a: PartRef, b: PartRef) { + return a.messageID === b.messageID && a.partID === b.partID +} + +function sameGroup(a: PartGroup, b: PartGroup) { + if (a === b) return true + if (a.key !== b.key) return false + if (a.type !== b.type) return false + if (a.type === "part") { + if (b.type !== "part") return false + return sameRef(a.ref, b.ref) + } + if (b.type !== "context") return false + if (a.refs.length !== b.refs.length) return false + return a.refs.every((ref, i) => sameRef(ref, b.refs[i]!)) +} + +function sameGroups(a: readonly PartGroup[] | undefined, b: readonly PartGroup[] | undefined) { + if (a === b) return true + if (!a || !b) return false + if (a.length !== b.length) return false + return a.every((item, i) => sameGroup(item, b[i]!)) +} + +function groupParts(parts: { messageID: string; part: PartType }[]) { + const result: PartGroup[] = [] + let start = -1 + + const flush = (end: number) => { + if (start < 0) return + const first = parts[start] + const last = parts[end] + if (!first || !last) { + start = -1 + return + } + result.push({ + key: `context:${first.part.id}`, + type: "context", + refs: parts.slice(start, end + 1).map((item) => ({ + messageID: item.messageID, + partID: item.part.id, + })), + }) + start = -1 + } + + parts.forEach((item, index) => { + if (isContextGroupTool(item.part)) { + if (start < 0) start = index + return + } + + flush(index - 1) + result.push({ + key: `part:${item.messageID}:${item.part.id}`, + type: "part", + ref: { + messageID: item.messageID, + partID: item.part.id, + }, + }) + }) + + flush(parts.length - 1) + return result +} + +function partByID(parts: readonly PartType[], partID: string) { + return parts.find((part) => part.id === partID) +} + function renderable(part: PartType, showReasoningSummaries = true) { if (part.type === "tool") { if (HIDDEN_TOOLS.has(part.tool)) return false @@ -298,101 +438,88 @@ export function AssistantParts(props: { }) { const data = useData() const emptyParts: PartType[] = [] + const emptyTools: ToolPart[] = [] - const grouped = createMemo(() => { - const keys: string[] = [] - const items: Record< - string, - { type: "part"; part: PartType; message: AssistantMessage } | { type: "context"; parts: ToolPart[] } - > = {} - const push = ( - key: string, - item: { type: "part"; part: PartType; message: AssistantMessage } | { type: "context"; parts: ToolPart[] }, - ) => { - keys.push(key) - items[key] = item - } + const grouped = createMemo( + () => + groupParts( + props.messages.flatMap((message) => + list(data.store.part?.[message.id], emptyParts) + .filter((part) => renderable(part, props.showReasoningSummaries ?? true)) + .map((part) => ({ + messageID: message.id, + part, + })), + ), + ), + [] as PartGroup[], + { equals: sameGroups }, + ) - const parts = props.messages.flatMap((message) => - list(data.store.part?.[message.id], emptyParts) - .filter((part) => renderable(part, props.showReasoningSummaries ?? true)) - .map((part) => ({ message, part })), - ) - - let start = -1 - - const flush = (end: number) => { - if (start < 0) return - const first = parts[start] - const last = parts[end] - if (!first || !last) { - start = -1 - return - } - push(`context:${first.part.id}`, { - type: "context", - parts: parts - .slice(start, end + 1) - .map((x) => x.part) - .filter((part): part is ToolPart => isContextGroupTool(part)), - }) - start = -1 - } - - parts.forEach((item, index) => { - if (isContextGroupTool(item.part)) { - if (start < 0) start = index - return - } - - flush(index - 1) - push(`part:${item.message.id}:${item.part.id}`, { type: "part", part: item.part, message: item.message }) - }) - - flush(parts.length - 1) - - return { keys, items } - }) - - const last = createMemo(() => grouped().keys.at(-1)) + const last = createMemo(() => grouped().at(-1)?.key) return ( - - {(key) => { - const item = createMemo(() => grouped().items[key]) - const ctx = createMemo(() => { - const value = item() - if (!value) return - if (value.type !== "context") return - return value - }) - const part = createMemo(() => { - const value = item() - if (!value) return - if (value.type !== "part") return - return value - }) - const tail = createMemo(() => last() === key) + + {(entryAccessor) => { + const entryType = createMemo(() => entryAccessor().type) + return ( - <> - - {(entry) => } - - - {(entry) => ( - - )} - - + + + {(() => { + const parts = createMemo( + () => { + const entry = entryAccessor() as { type: "context"; refs: PartRef[] } + return entry.refs + .map((ref) => partByID(list(data.store.part?.[ref.messageID], emptyParts), ref.partID)) + .filter((part): part is ToolPart => !!part && isContextGroupTool(part)) + }, + emptyTools, + { equals: same }, + ) + const busy = createMemo(() => props.working && last() === entryAccessor().key) + + return ( + 0}> + + + ) + })()} + + + {(() => { + const message = createMemo(() => { + const entry = entryAccessor() as { type: "part"; ref: PartRef } + return props.messages.find((item) => item.id === entry.ref.messageID) + }) + const part = createMemo(() => { + const entry = entryAccessor() as { type: "part"; ref: PartRef } + return partByID(list(data.store.part?.[entry.ref.messageID], emptyParts), entry.ref.partID) + }) + + return ( + + {(msg) => ( + + {(p) => ( + + )} + + )} + + ) + })()} + + ) }} - + ) } @@ -463,23 +590,11 @@ function contextToolTrigger(part: ToolPart, i18n: ReturnType) { } } -function contextToolSummary(parts: ToolPart[], i18n: ReturnType) { +function contextToolSummary(parts: ToolPart[]) { const read = parts.filter((part) => part.tool === "read").length const search = parts.filter((part) => part.tool === "glob" || part.tool === "grep").length const list = parts.filter((part) => part.tool === "list").length - return [ - read - ? i18n.t(read === 1 ? "ui.messagePart.context.read.one" : "ui.messagePart.context.read.other", { count: read }) - : undefined, - search - ? i18n.t(search === 1 ? "ui.messagePart.context.search.one" : "ui.messagePart.context.search.other", { - count: search, - }) - : undefined, - list - ? i18n.t(list === 1 ? "ui.messagePart.context.list.one" : "ui.messagePart.context.list.other", { count: list }) - : undefined, - ].filter((value): value is string => !!value) + return { read, search, list } } export function registerPartComponent(type: string, component: PartComponent) { @@ -495,6 +610,7 @@ export function Message(props: MessageProps) { message={userMessage() as UserMessage} parts={props.parts} interrupted={props.interrupted} + queued={props.queued} /> )} @@ -518,81 +634,72 @@ export function AssistantMessageDisplay(props: { showAssistantCopyPartID?: string | null showReasoningSummaries?: boolean }) { - const grouped = createMemo(() => { - const keys: string[] = [] - const items: Record = {} - const push = (key: string, item: { type: "part"; part: PartType } | { type: "context"; parts: ToolPart[] }) => { - keys.push(key) - items[key] = item - } - - const parts = props.parts - let start = -1 - - const flush = (end: number) => { - if (start < 0) return - const first = parts[start] - const last = parts[end] - if (!first || !last) { - start = -1 - return - } - push(`context:${first.id}`, { - type: "context", - parts: parts.slice(start, end + 1).filter((part): part is ToolPart => isContextGroupTool(part)), - }) - start = -1 - } - - parts.forEach((part, index) => { - if (!renderable(part, props.showReasoningSummaries ?? true)) return - - if (isContextGroupTool(part)) { - if (start < 0) start = index - return - } - - flush(index - 1) - push(`part:${part.id}`, { type: "part", part }) - }) - - flush(parts.length - 1) - - return { keys, items } - }) + const emptyTools: ToolPart[] = [] + const grouped = createMemo( + () => + groupParts( + props.parts + .filter((part) => renderable(part, props.showReasoningSummaries ?? true)) + .map((part) => ({ + messageID: props.message.id, + part, + })), + ), + [] as PartGroup[], + { equals: sameGroups }, + ) return ( - - {(key) => { - const item = createMemo(() => grouped().items[key]) - const ctx = createMemo(() => { - const value = item() - if (!value) return - if (value.type !== "context") return - return value - }) - const part = createMemo(() => { - const value = item() - if (!value) return - if (value.type !== "part") return - return value - }) + + {(entryAccessor) => { + const entryType = createMemo(() => entryAccessor().type) + return ( - <> - {(entry) => } - - {(entry) => ( - - )} - - + + + {(() => { + const parts = createMemo( + () => { + const entry = entryAccessor() as { type: "context"; refs: PartRef[] } + return entry.refs + .map((ref) => partByID(props.parts, ref.partID)) + .filter((part): part is ToolPart => !!part && isContextGroupTool(part)) + }, + emptyTools, + { equals: same }, + ) + + return ( + 0}> + + + ) + })()} + + + {(() => { + const part = createMemo(() => { + const entry = entryAccessor() as { type: "part"; ref: PartRef } + return partByID(props.parts, entry.ref.partID) + }) + + return ( + + {(p) => ( + + )} + + ) + })()} + + ) }} - + ) } @@ -603,42 +710,64 @@ function ContextToolGroup(props: { parts: ToolPart[]; busy?: boolean }) { () => !!props.busy || props.parts.some((part) => part.state.status === "pending" || part.state.status === "running"), ) - const summary = createMemo(() => contextToolSummary(props.parts, i18n)) - const details = createMemo(() => summary().join(", ")) + const summary = createMemo(() => contextToolSummary(props.parts)) return (
- - {i18n.t("ui.sessionTurn.status.gatheredContext")} - - {details()} - - - } + - - - - - - {details()} - + + - + + + +
- - {(part) => { - const trigger = contextToolTrigger(part, i18n) - const running = part.state.status === "pending" || part.state.status === "running" + + {(partAccessor) => { + const trigger = createMemo(() => contextToolTrigger(partAccessor(), i18n)) + const running = createMemo( + () => partAccessor().state.status === "pending" || partAccessor().state.status === "running", + ) return (
@@ -647,15 +776,13 @@ function ContextToolGroup(props: { parts: ToolPart[]; busy?: boolean }) {
- - - + - - {trigger.subtitle} + + {trigger().subtitle} - - + + {(arg) => {arg}} @@ -667,14 +794,19 @@ function ContextToolGroup(props: { parts: ToolPart[]; busy?: boolean }) {
) }} - +
) } -export function UserMessageDisplay(props: { message: UserMessage; parts: PartType[]; interrupted?: boolean }) { +export function UserMessageDisplay(props: { + message: UserMessage + parts: PartType[] + interrupted?: boolean + queued?: boolean +}) { const data = useData() const dialog = useDialog() const i18n = useI18n() @@ -754,6 +886,7 @@ export function UserMessageDisplay(props: { message: UserMessage; parts: PartTyp
{ if (file.mime.startsWith("image/") && file.url) { openImagePreview(file.url, file.filename) @@ -782,9 +915,14 @@ export function UserMessageDisplay(props: { message: UserMessage; parts: PartTyp <>
-
+
+ +
+ +
+
@@ -960,30 +1098,30 @@ function ToolFileAccordion(props: { path: string; actions?: JSX.Element; childre PART_MAPPING["tool"] = function ToolPartDisplay(props) { const i18n = useI18n() - const part = props.part as ToolPart - if (part.tool === "todowrite" || part.tool === "todoread") return null + const part = () => props.part as ToolPart + if (part().tool === "todowrite" || part().tool === "todoread") return null const hideQuestion = createMemo( - () => part.tool === "question" && (part.state.status === "pending" || part.state.status === "running"), + () => part().tool === "question" && (part().state.status === "pending" || part().state.status === "running"), ) const emptyInput: Record = {} const emptyMetadata: Record = {} - const input = () => part.state?.input ?? emptyInput + const input = () => part().state?.input ?? emptyInput // @ts-expect-error - const partMetadata = () => part.state?.metadata ?? emptyMetadata + const partMetadata = () => part().state?.metadata ?? emptyMetadata - const render = ToolRegistry.render(part.tool) ?? GenericTool + const render = createMemo(() => ToolRegistry.render(part().tool) ?? GenericTool) return (
- + {(error) => { const cleaned = error().replace("Error: ", "") - if (part.tool === "question" && cleaned.includes("dismissed this question")) { + if (part().tool === "question" && cleaned.includes("dismissed this question")) { return (
@@ -1015,13 +1153,13 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) { @@ -1032,10 +1170,25 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) { ) } +PART_MAPPING["compaction"] = function CompactionPartDisplay() { + const i18n = useI18n() + return ( +
+
+ + + {i18n.t("ui.messagePart.compaction")} + + +
+
+ ) +} + PART_MAPPING["text"] = function TextPartDisplay(props) { const data = useData() const i18n = useI18n() - const part = props.part as TextPart + const part = () => props.part as TextPart const interrupted = createMemo( () => props.message.role === "assistant" && (props.message as AssistantMessage).error?.name === "MessageAbortedError", @@ -1078,18 +1231,18 @@ PART_MAPPING["text"] = function TextPartDisplay(props) { return items.filter((x) => !!x).join(" \u00B7 ") }) - const displayText = () => (part.text ?? "").trim() + const displayText = () => (part().text ?? "").trim() const throttledText = createThrottledValue(displayText) const isLastTextPart = createMemo(() => { const last = (data.store.part?.[props.message.id] ?? []) .filter((item): item is TextPart => item?.type === "text" && !!item.text?.trim()) .at(-1) - return last?.id === part.id + return last?.id === part().id }) const showCopy = createMemo(() => { if (props.message.role !== "assistant") return isLastTextPart() if (props.showAssistantCopyPartID === null) return false - if (typeof props.showAssistantCopyPartID === "string") return props.showAssistantCopyPartID === part.id + if (typeof props.showAssistantCopyPartID === "string") return props.showAssistantCopyPartID === part().id return isLastTextPart() }) const [copied, setCopied] = createSignal(false) @@ -1106,7 +1259,7 @@ PART_MAPPING["text"] = function TextPartDisplay(props) {
- +
@@ -1137,14 +1290,14 @@ PART_MAPPING["text"] = function TextPartDisplay(props) { } PART_MAPPING["reasoning"] = function ReasoningPartDisplay(props) { - const part = props.part as ReasoningPart - const text = () => part.text.trim() + const part = () => props.part as ReasoningPart + const text = () => part().text.trim() const throttledText = createThrottledValue(text) return (
- +
) @@ -1286,9 +1439,7 @@ ToolRegistry.register({
+ } >
@@ -1475,9 +1636,7 @@ ToolRegistry.register({
- - - + {filename()} @@ -1547,9 +1706,7 @@ ToolRegistry.register({
- - - + {filename()} @@ -1741,9 +1898,7 @@ ToolRegistry.register({
- - - + {getFilename(file().relativePath)} @@ -1900,3 +2055,25 @@ ToolRegistry.register({ ) }, }) + +ToolRegistry.register({ + name: "skill", + render(props) { + const title = createMemo(() => props.input.name || "skill") + const running = createMemo(() => props.status === "pending" || props.status === "running") + + const titleContent = () => + + const trigger = () => ( +
+
+ + {titleContent()} + +
+
+ ) + + return + }, +}) diff --git a/packages/ui/src/components/motion-spring.tsx b/packages/ui/src/components/motion-spring.tsx new file mode 100644 index 0000000000..a5104a1a3e --- /dev/null +++ b/packages/ui/src/components/motion-spring.tsx @@ -0,0 +1,45 @@ +import { attachSpring, motionValue } from "motion" +import type { SpringOptions } from "motion" +import { createEffect, createSignal, onCleanup } from "solid-js" + +type Opt = Partial> +const eq = (a: Opt | undefined, b: Opt | undefined) => + a?.visualDuration === b?.visualDuration && + a?.bounce === b?.bounce && + a?.stiffness === b?.stiffness && + a?.damping === b?.damping && + a?.mass === b?.mass && + a?.velocity === b?.velocity + +export function useSpring(target: () => number, options?: Opt | (() => Opt)) { + const read = () => (typeof options === "function" ? options() : options) + const [value, setValue] = createSignal(target()) + const source = motionValue(value()) + const spring = motionValue(value()) + let config = read() + let stop = attachSpring(spring, source, config) + let off = spring.on("change", (next: number) => setValue(next)) + + createEffect(() => { + source.set(target()) + }) + + createEffect(() => { + if (!options) return + const next = read() + if (eq(config, next)) return + config = next + stop() + stop = attachSpring(spring, source, next) + setValue(spring.get()) + }) + + onCleanup(() => { + off() + stop() + spring.destroy() + source.destroy() + }) + + return value +} diff --git a/packages/ui/src/components/provider-icon.tsx b/packages/ui/src/components/provider-icon.tsx index d653765a55..edfdd03571 100644 --- a/packages/ui/src/components/provider-icon.tsx +++ b/packages/ui/src/components/provider-icon.tsx @@ -1,14 +1,15 @@ import type { Component, JSX } from "solid-js" -import { splitProps } from "solid-js" +import { createMemo, splitProps } from "solid-js" import sprite from "./provider-icons/sprite.svg" -import type { IconName } from "./provider-icons/types" +import { iconNames, type IconName } from "./provider-icons/types" export type ProviderIconProps = JSX.SVGElementTags["svg"] & { - id: IconName + id: string } export const ProviderIcon: Component = (props) => { const [local, rest] = splitProps(props, ["id", "class", "classList"]) + const resolved = createMemo(() => (iconNames.includes(local.id as IconName) ? local.id : "synthetic")) return ( = (props) => { [local.class ?? ""]: !!local.class, }} > - + ) } diff --git a/packages/ui/src/components/radio-group.css b/packages/ui/src/components/radio-group.css index 4faaa33f43..e9cc711846 100644 --- a/packages/ui/src/components/radio-group.css +++ b/packages/ui/src/components/radio-group.css @@ -48,9 +48,9 @@ transition: opacity 200ms ease-out, box-shadow 100ms ease-in-out, - width 200ms ease-out, - height 200ms ease-out, - transform 200ms ease-out; + width 200ms cubic-bezier(0.22, 1.2, 0.36, 1), + height 200ms cubic-bezier(0.22, 1.2, 0.36, 1), + transform 300ms cubic-bezier(0.22, 1.2, 0.36, 1); will-change: transform; z-index: 0; } diff --git a/packages/ui/src/components/scroll-view.css b/packages/ui/src/components/scroll-view.css index f81ae29766..f6a49e241c 100644 --- a/packages/ui/src/components/scroll-view.css +++ b/packages/ui/src/components/scroll-view.css @@ -19,7 +19,7 @@ position: absolute; right: 0; top: 0; - width: 16px; + width: 12px; transition: opacity 200ms ease; cursor: default; user-select: none; @@ -29,10 +29,11 @@ .scroll-view__thumb::after { content: ""; position: absolute; - right: 4px; + left: 50%; + transform: translateX(-50%); top: 0; bottom: 0; - width: 6px; + width: 4px; border-radius: 9999px; background-color: var(--border-weak-base); backdrop-filter: blur(4px); diff --git a/packages/ui/src/components/session-retry.tsx b/packages/ui/src/components/session-retry.tsx new file mode 100644 index 0000000000..ac0eb035d9 --- /dev/null +++ b/packages/ui/src/components/session-retry.tsx @@ -0,0 +1,74 @@ +import { createEffect, createMemo, createSignal, on, onCleanup, Show } from "solid-js" +import type { SessionStatus } from "@opencode-ai/sdk/v2/client" +import { useI18n } from "../context/i18n" +import { Card } from "./card" +import { Tooltip } from "./tooltip" +import { Spinner } from "./spinner" + +export function SessionRetry(props: { status: SessionStatus; show?: boolean }) { + const i18n = useI18n() + const retry = createMemo(() => { + if (props.status.type !== "retry") return + return props.status + }) + const [seconds, setSeconds] = createSignal(0) + createEffect( + on(retry, (current) => { + if (!current) return + const update = () => { + const next = retry()?.next + if (!next) return + setSeconds(Math.round((next - Date.now()) / 1000)) + } + update() + const timer = setInterval(update, 1000) + onCleanup(() => clearInterval(timer)) + }), + ) + const message = createMemo(() => { + const current = retry() + if (!current) return "" + if (current.message.includes("exceeded your current quota") && current.message.includes("gemini")) { + return i18n.t("ui.sessionTurn.retry.geminiHot") + } + if (current.message.length > 80) return current.message.slice(0, 80) + "..." + return current.message + }) + const truncated = createMemo(() => { + const current = retry() + if (!current) return false + return current.message.length > 80 + }) + const info = createMemo(() => { + const current = retry() + if (!current) return "" + const count = Math.max(0, seconds()) + const delay = count > 0 ? i18n.t("ui.sessionTurn.retry.inSeconds", { seconds: count }) : "" + const retrying = i18n.t("ui.sessionTurn.retry.retrying") + const line = [retrying, delay].filter(Boolean).join(" ") + if (!line) return i18n.t("ui.sessionTurn.retry.attempt", { attempt: current.attempt }) + return i18n.t("ui.sessionTurn.retry.attemptLine", { line, attempt: current.attempt }) + }) + + return ( + +
+ +
+ +
+ {message()}
}> + +
+ {message()} +
+
+ + {(line) =>
{line()}
}
+
+
+ +
+ + ) +} diff --git a/packages/ui/src/components/session-review.css b/packages/ui/src/components/session-review.css index 60da85e6f2..014a70e740 100644 --- a/packages/ui/src/components/session-review.css +++ b/packages/ui/src/components/session-review.css @@ -3,11 +3,10 @@ flex-direction: column; gap: 0px; height: 100%; - overflow-y: auto; - scrollbar-width: none; - contain: strict; - &::-webkit-scrollbar { - display: none; + + [data-slot="session-review-scroll"] { + flex: 1 1 auto; + min-height: 0; } .scroll-view__viewport { @@ -17,13 +16,11 @@ [data-slot="session-review-container"] { flex: 1 1 auto; - padding-right: 4px; + padding-right: 0; } [data-slot="session-review-header"] { - position: sticky; - top: 0; - z-index: 20; + z-index: 120; background-color: var(--background-stronger); height: 40px; padding-bottom: 8px; @@ -63,7 +60,7 @@ } [data-component="sticky-accordion-header"] { - --sticky-accordion-top: 40px; + --sticky-accordion-top: 0px; } [data-slot="session-review-accordion-item"][data-selected] diff --git a/packages/ui/src/components/session-review.tsx b/packages/ui/src/components/session-review.tsx index 77bd9506dc..c75baf921a 100644 --- a/packages/ui/src/components/session-review.tsx +++ b/packages/ui/src/components/session-review.tsx @@ -554,20 +554,7 @@ export const SessionReview = (props: SessionReviewProps) => { } return ( - { - scroll = el - props.scrollRef?.(el) - }} - onScroll={props.onScroll as any} - onKeyDown={handleReviewKeyDown} - classList={{ - ...(props.classList ?? {}), - [props.classes?.root ?? ""]: !!props.classes?.root, - [props.class ?? ""]: !!props.class, - }} - > +
{props.title ?? i18n.t("ui.sessionReview.title")}
@@ -599,301 +586,319 @@ export const SessionReview = (props: SessionReviewProps) => { {props.actions}
- - (searchHits().length ? Math.min(searchActive(), searchHits().length - 1) : 0)} - count={() => searchHits().length} - setInput={(el) => { - searchInput = el - }} - onInput={(value) => { - setSearchQuery(value) - setSearchActive(0) - }} - onKeyDown={(event) => handleSearchInputKeyDown(event)} - onClose={closeSearch} - onPrev={() => navigateSearch(-1)} - onNext={() => navigateSearch(1)} - /> - -
- - - - {(file) => { - let wrapper: HTMLDivElement | undefined - const diff = createMemo(() => diffs().get(file)) - const item = () => diff()! + { + scroll = el + props.scrollRef?.(el) + }} + onScroll={props.onScroll as any} + onKeyDown={handleReviewKeyDown} + classList={{ + [props.classes?.root ?? ""]: !!props.classes?.root, + }} + > + + (searchHits().length ? Math.min(searchActive(), searchHits().length - 1) : 0)} + count={() => searchHits().length} + setInput={(el) => { + searchInput = el + }} + onInput={(value) => { + setSearchQuery(value) + setSearchActive(0) + }} + onKeyDown={(event) => handleSearchInputKeyDown(event)} + onClose={closeSearch} + onPrev={() => navigateSearch(-1)} + onNext={() => navigateSearch(1)} + /> + - const expanded = createMemo(() => open().includes(file)) - const force = () => !!store.force[file] +
+ +
+ + + {(file) => { + let wrapper: HTMLDivElement | undefined - const comments = createMemo(() => (props.comments ?? []).filter((c) => c.file === file)) - const commentedLines = createMemo(() => comments().map((c) => c.selection)) + const diff = createMemo(() => diffs().get(file)) + const item = () => diff()! - const beforeText = () => (typeof item().before === "string" ? item().before : "") - const afterText = () => (typeof item().after === "string" ? item().after : "") - const changedLines = () => item().additions + item().deletions - const mediaKind = createMemo(() => mediaKindFromPath(file)) + const expanded = createMemo(() => open().includes(file)) + const force = () => !!store.force[file] - const tooLarge = createMemo(() => { - if (!expanded()) return false - if (force()) return false - if (mediaKind()) return false - return changedLines() > MAX_DIFF_CHANGED_LINES - }) + const comments = createMemo(() => (props.comments ?? []).filter((c) => c.file === file)) + const commentedLines = createMemo(() => comments().map((c) => c.selection)) - const isAdded = () => item().status === "added" || (beforeText().length === 0 && afterText().length > 0) - const isDeleted = () => - item().status === "deleted" || (afterText().length === 0 && beforeText().length > 0) + const beforeText = () => (typeof item().before === "string" ? item().before : "") + const afterText = () => (typeof item().after === "string" ? item().after : "") + const changedLines = () => item().additions + item().deletions + const mediaKind = createMemo(() => mediaKindFromPath(file)) - const selectedLines = createMemo(() => { - const current = selection() - if (!current || current.file !== file) return null - return current.range - }) + const tooLarge = createMemo(() => { + if (!expanded()) return false + if (force()) return false + if (mediaKind()) return false + return changedLines() > MAX_DIFF_CHANGED_LINES + }) - const draftRange = createMemo(() => { - const current = commenting() - if (!current || current.file !== file) return null - return current.range - }) + const isAdded = () => + item().status === "added" || (beforeText().length === 0 && afterText().length > 0) + const isDeleted = () => + item().status === "deleted" || (afterText().length === 0 && beforeText().length > 0) - const commentsUi = createLineCommentController({ - comments, - label: i18n.t("ui.lineComment.submit"), - draftKey: () => file, - state: { - opened: () => { - const current = opened() + const selectedLines = createMemo(() => { + const current = selection() if (!current || current.file !== file) return null - return current.id - }, - setOpened: (id) => setOpened(id ? { file, id } : null), - selected: selectedLines, - setSelected: (range) => setSelection(range ? { file, range } : null), - commenting: draftRange, - setCommenting: (range) => setCommenting(range ? { file, range } : null), - }, - getSide: selectionSide, - clearSelectionOnSelectionEndNull: false, - onSubmit: ({ comment, selection }) => { - props.onLineComment?.({ - file, - selection, - comment, - preview: selectionPreview(item(), selection), + return current.range }) - }, - onUpdate: ({ id, comment, selection }) => { - props.onLineCommentUpdate?.({ - id, - file, - selection, - comment, - preview: selectionPreview(item(), selection), + + const draftRange = createMemo(() => { + const current = commenting() + if (!current || current.file !== file) return null + return current.range }) - }, - onDelete: (comment) => { - props.onLineCommentDelete?.({ - id: comment.id, - file, + + const commentsUi = createLineCommentController({ + comments, + label: i18n.t("ui.lineComment.submit"), + draftKey: () => file, + state: { + opened: () => { + const current = opened() + if (!current || current.file !== file) return null + return current.id + }, + setOpened: (id) => setOpened(id ? { file, id } : null), + selected: selectedLines, + setSelected: (range) => setSelection(range ? { file, range } : null), + commenting: draftRange, + setCommenting: (range) => setCommenting(range ? { file, range } : null), + }, + getSide: selectionSide, + clearSelectionOnSelectionEndNull: false, + onSubmit: ({ comment, selection }) => { + props.onLineComment?.({ + file, + selection, + comment, + preview: selectionPreview(item(), selection), + }) + }, + onUpdate: ({ id, comment, selection }) => { + props.onLineCommentUpdate?.({ + id, + file, + selection, + comment, + preview: selectionPreview(item(), selection), + }) + }, + onDelete: (comment) => { + props.onLineCommentDelete?.({ + id: comment.id, + file, + }) + }, + editSubmitLabel: props.lineCommentActions?.saveLabel, + renderCommentActions: props.lineCommentActions + ? (comment, controls) => ( + + ) + : undefined, }) - }, - editSubmitLabel: props.lineCommentActions?.saveLabel, - renderCommentActions: props.lineCommentActions - ? (comment, controls) => ( - - ) - : undefined, - }) - onCleanup(() => { - anchors.delete(file) - readyFiles.delete(file) - searchHandles.delete(file) - if (highlightedFile === file) highlightedFile = undefined - }) + onCleanup(() => { + anchors.delete(file) + readyFiles.delete(file) + searchHandles.delete(file) + if (highlightedFile === file) highlightedFile = undefined + }) - const handleLineSelected = (range: SelectedLineRange | null) => { - if (!props.onLineComment) return - commentsUi.onLineSelected(range) - } + const handleLineSelected = (range: SelectedLineRange | null) => { + if (!props.onLineComment) return + commentsUi.onLineSelected(range) + } - const handleLineSelectionEnd = (range: SelectedLineRange | null) => { - if (!props.onLineComment) return - commentsUi.onLineSelectionEnd(range) - } + const handleLineSelectionEnd = (range: SelectedLineRange | null) => { + if (!props.onLineComment) return + commentsUi.onLineSelectionEnd(range) + } - return ( - - - -
-
- -
- - {`\u202A${getDirectory(file)}\u202C`} - - {getFilename(file)} - - - - - -
-
-
- - -
- - {i18n.t("ui.sessionReview.change.added")} - - -
-
- - - {i18n.t("ui.sessionReview.change.removed")} - - - - - {i18n.t("ui.sessionReview.change.modified")} - - - - - -
- - - -
-
-
-
- -
{ - wrapper = el - anchors.set(file, el) - }} + return ( + - - - -
-
- {i18n.t("ui.sessionReview.largeDiff.title")} -
-
- {i18n.t("ui.sessionReview.largeDiff.meta", { - limit: MAX_DIFF_CHANGED_LINES.toLocaleString(), - current: changedLines().toLocaleString(), - })} -
-
- + + +
+
+ +
+ + {`\u202A${getDirectory(file)}\u202C`} + + {getFilename(file)} + + + + +
- - - { - readyFiles.add(file) - props.onDiffRendered?.() - }} - enableLineSelection={props.onLineComment != null} - enableHoverUtility={props.onLineComment != null} - onLineSelected={handleLineSelected} - onLineSelectionEnd={handleLineSelectionEnd} - onLineNumberSelectionEnd={commentsUi.onLineNumberSelectionEnd} - annotations={commentsUi.annotations()} - renderAnnotation={commentsUi.renderAnnotation} - renderHoverUtility={props.onLineComment ? commentsUi.renderHoverUtility : undefined} - selectedLines={selectedLines()} - commentedLines={commentedLines()} - search={{ - shortcuts: "disabled", - showBar: false, - disableVirtualization: searchExpanded(), - register: (handle: FileSearchHandle | null) => { - if (!handle) { - searchHandles.delete(file) - readyFiles.delete(file) - if (highlightedFile === file) highlightedFile = undefined - return - } +
+ + +
+ + {i18n.t("ui.sessionReview.change.added")} + + +
+
+ + + {i18n.t("ui.sessionReview.change.removed")} + + + + + {i18n.t("ui.sessionReview.change.modified")} + + + + + +
+ + + +
+
+
+
+ +
{ + wrapper = el + anchors.set(file, el) + }} + > + + + +
+
+ {i18n.t("ui.sessionReview.largeDiff.title")} +
+
+ {i18n.t("ui.sessionReview.largeDiff.meta", { + limit: MAX_DIFF_CHANGED_LINES.toLocaleString(), + current: changedLines().toLocaleString(), + })} +
+
+ +
+
+
+ + { + readyFiles.add(file) + props.onDiffRendered?.() + }} + enableLineSelection={props.onLineComment != null} + enableHoverUtility={props.onLineComment != null} + onLineSelected={handleLineSelected} + onLineSelectionEnd={handleLineSelectionEnd} + onLineNumberSelectionEnd={commentsUi.onLineNumberSelectionEnd} + annotations={commentsUi.annotations()} + renderAnnotation={commentsUi.renderAnnotation} + renderHoverUtility={props.onLineComment ? commentsUi.renderHoverUtility : undefined} + selectedLines={selectedLines()} + commentedLines={commentedLines()} + search={{ + shortcuts: "disabled", + showBar: false, + disableVirtualization: searchExpanded(), + register: (handle: FileSearchHandle | null) => { + if (!handle) { + searchHandles.delete(file) + readyFiles.delete(file) + if (highlightedFile === file) highlightedFile = undefined + return + } - searchHandles.set(file, handle) - }, - }} - before={{ - name: file, - contents: typeof item().before === "string" ? item().before : "", - }} - after={{ - name: file, - contents: typeof item().after === "string" ? item().after : "", - }} - media={{ - mode: "auto", - path: file, - before: item().before, - after: item().after, - readFile: props.readFile, - }} - /> - -
-
-
-
- - ) - }} - - - -
- + searchHandles.set(file, handle) + }, + }} + before={{ + name: file, + contents: typeof item().before === "string" ? item().before : "", + }} + after={{ + name: file, + contents: typeof item().after === "string" ? item().after : "", + }} + media={{ + mode: "auto", + path: file, + before: item().before, + after: item().after, + readFile: props.readFile, + }} + /> + + + +
+ +
+ ) + }} + + +
+ +
+ +
) } diff --git a/packages/ui/src/components/session-turn.css b/packages/ui/src/components/session-turn.css index 9639e6635a..15d7b50352 100644 --- a/packages/ui/src/components/session-turn.css +++ b/packages/ui/src/components/session-turn.css @@ -37,6 +37,12 @@ max-width: 100%; } + [data-slot="session-turn-compaction"] { + width: 100%; + min-width: 0; + align-self: stretch; + } + [data-slot="session-turn-thinking"] { display: flex; align-items: center; @@ -47,23 +53,20 @@ font-family: var(--font-family-sans); font-size: var(--font-size-base); font-weight: var(--font-weight-medium); - line-height: var(--line-height-large); + line-height: 20px; min-height: 20px; [data-component="spinner"] { width: 16px; height: 16px; } + } - [data-slot="session-turn-thinking-heading"] { - flex: 1 1 auto; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - color: var(--text-weaker); - font-weight: var(--font-weight-regular); - } + [data-component="text-reveal"].session-turn-thinking-heading { + flex: 1 1 auto; + min-width: 0; + color: var(--text-weaker); + font-weight: var(--font-weight-regular); } .error-card { diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx index 3116d4b65c..a8a41b8ef4 100644 --- a/packages/ui/src/components/session-turn.tsx +++ b/packages/ui/src/components/session-turn.tsx @@ -1,4 +1,5 @@ import { AssistantMessage, type FileDiff, Message as MessageType, Part as PartType } from "@opencode-ai/sdk/v2/client" +import type { SessionStatus } from "@opencode-ai/sdk/v2" import { useData } from "../context" import { useFileComponent } from "../context/file" @@ -6,7 +7,7 @@ import { Binary } from "@opencode-ai/util/binary" import { getDirectory, getFilename } from "@opencode-ai/util/path" import { createEffect, createMemo, createSignal, For, on, ParentProps, Show } from "solid-js" import { Dynamic } from "solid-js/web" -import { AssistantParts, Message, PART_MAPPING } from "./message-part" +import { AssistantParts, Message, Part, PART_MAPPING } from "./message-part" import { Card } from "./card" import { Accordion } from "./accordion" import { StickyAccordionHeader } from "./sticky-accordion-header" @@ -14,6 +15,8 @@ import { Collapsible } from "./collapsible" import { DiffChanges } from "./diff-changes" import { Icon } from "./icon" import { TextShimmer } from "./text-shimmer" +import { SessionRetry } from "./session-retry" +import { TextReveal } from "./text-reveal" import { createAutoScroll } from "../hooks" import { useI18n } from "../context/i18n" @@ -138,10 +141,12 @@ export function SessionTurn( props: ParentProps<{ sessionID: string messageID: string - lastUserMessageID?: string showReasoningSummaries?: boolean shellToolDefaultOpen?: boolean editToolDefaultOpen?: boolean + active?: boolean + queued?: boolean + status?: SessionStatus onUserInteracted?: () => void classes?: { root?: string @@ -186,18 +191,41 @@ export function SessionTurn( return msg }) - const lastUserMessageID = createMemo(() => { - if (props.lastUserMessageID) return props.lastUserMessageID - + const pending = createMemo(() => { + if (typeof props.active === "boolean" && typeof props.queued === "boolean") return const messages = allMessages() ?? emptyMessages - for (let i = messages.length - 1; i >= 0; i--) { - const msg = messages[i] - if (msg?.role === "user") return msg.id - } - return undefined + return messages.findLast( + (item): item is AssistantMessage => item.role === "assistant" && typeof item.time.completed !== "number", + ) }) - const isLastUserMessage = createMemo(() => props.messageID === lastUserMessageID()) + const pendingUser = createMemo(() => { + const item = pending() + if (!item?.parentID) return + const messages = allMessages() ?? emptyMessages + const result = Binary.search(messages, item.parentID, (m) => m.id) + const msg = result.found ? messages[result.index] : messages.find((m) => m.id === item.parentID) + if (!msg || msg.role !== "user") return + return msg + }) + + const active = createMemo(() => { + if (typeof props.active === "boolean") return props.active + const msg = message() + const parent = pendingUser() + if (!msg || !parent) return false + return parent.id === msg.id + }) + + const queued = createMemo(() => { + if (typeof props.queued === "boolean") return props.queued + const id = message()?.id + if (!id) return false + if (!pendingUser()) return false + const item = pending() + if (!item) return false + return id > item.id + }) const parts = createMemo(() => { const msg = message() @@ -205,6 +233,8 @@ export function SessionTurn( return list(data.store.part?.[msg.id], emptyParts) }) + const compaction = createMemo(() => parts().find((part) => part.type === "compaction")) + const diffs = createMemo(() => { const files = message()?.summary?.diffs if (!files?.length) return emptyDiffs @@ -283,8 +313,12 @@ export function SessionTurn( return unwrap(String(msg)) }) - const status = createMemo(() => data.store.session_status[props.sessionID] ?? idle) - const working = createMemo(() => status().type !== "idle" && isLastUserMessage()) + const status = createMemo(() => { + if (props.status !== undefined) return props.status + if (typeof props.active === "boolean" && !props.active) return idle + return data.store.session_status[props.sessionID] ?? idle + }) + const working = createMemo(() => status().type !== "idle" && active()) const showReasoningSummaries = createMemo(() => props.showReasoningSummaries ?? true) const assistantCopyPartID = createMemo(() => { @@ -332,8 +366,9 @@ export function SessionTurn( ) const showThinking = createMemo(() => { if (!working() || !!error()) return false + if (queued()) return false + if (status().type === "retry") return false if (showReasoningSummaries()) return assistantVisible() === 0 - if (assistantTailVisible() === "text") return false return true }) @@ -361,8 +396,15 @@ export function SessionTurn( class={props.classes?.container} >
- +
+ + {(part) => ( +
+ +
+ )} +
0}>
- - {(text) => {text()}} + +
+ 0 && !working()}>
diff --git a/packages/ui/src/components/shell-submessage-motion.stories.tsx b/packages/ui/src/components/shell-submessage-motion.stories.tsx new file mode 100644 index 0000000000..1f53b6e4de --- /dev/null +++ b/packages/ui/src/components/shell-submessage-motion.stories.tsx @@ -0,0 +1,329 @@ +// @ts-nocheck +import { createEffect, createSignal, onCleanup } from "solid-js" +import { BasicTool } from "./basic-tool" +import { animate } from "motion" + +export default { + title: "UI/Shell Submessage Motion", + id: "components-shell-submessage-motion", + tags: ["autodocs"], + parameters: { + docs: { + description: { + component: `### Overview +Interactive playground for animating the Shell tool subtitle ("submessage") in the timeline trigger row. + +### Production component path +- Trigger layout: \`packages/ui/src/components/basic-tool.tsx\` +- Bash tool subtitle source: \`packages/ui/src/components/message-part.tsx\` (tool: \`bash\`, \`trigger.subtitle\`) + +### What this playground tunes +- Width reveal (spring-driven pixel width via \`useSpring\`) +- Opacity fade +- Blur settle`, + }, + }, + }, +} + +const btn = (accent?: boolean) => + ({ + padding: "6px 14px", + "border-radius": "6px", + border: "1px solid var(--color-divider, #333)", + background: accent ? "var(--color-accent, #58f)" : "var(--color-fill-element, #222)", + color: "var(--color-text, #eee)", + cursor: "pointer", + "font-size": "13px", + }) as const + +const sliderLabel = { + "font-size": "11px", + "font-family": "monospace", + color: "var(--color-text-weak, #666)", + "min-width": "84px", + "flex-shrink": "0", + "text-align": "right", +} + +const sliderValue = { + "font-family": "monospace", + "font-size": "11px", + color: "var(--color-text-weak, #aaa)", + "min-width": "76px", +} + +const shellCss = ` +[data-component="shell-submessage-scene"] [data-component="tool-trigger"] [data-slot="basic-tool-tool-info-main"] { + align-items: baseline; +} + +[data-component="shell-submessage"] { + min-width: 0; + max-width: 100%; + display: inline-flex; + align-items: baseline; + vertical-align: baseline; +} + +[data-component="shell-submessage"] [data-slot="shell-submessage-width"] { + min-width: 0; + max-width: 100%; + display: inline-flex; + align-items: baseline; + overflow: hidden; +} + +[data-component="shell-submessage"] [data-slot="shell-submessage-value"] { + display: inline-block; + vertical-align: baseline; + min-width: 0; + line-height: inherit; + white-space: nowrap; + opacity: 0; + filter: blur(var(--shell-sub-blur, 2px)); + transition-property: opacity, filter; + transition-duration: var(--shell-sub-fade-ms, 320ms); + transition-timing-function: var(--shell-sub-fade-ease, cubic-bezier(0.22, 1, 0.36, 1)); +} + +[data-component="shell-submessage"][data-visible] [data-slot="shell-submessage-value"] { + opacity: 1; + filter: blur(0px); +} +` + +const ease = { + smooth: "cubic-bezier(0.16, 1, 0.3, 1)", + snappy: "cubic-bezier(0.22, 1, 0.36, 1)", + standard: "cubic-bezier(0.2, 0.8, 0.2, 1)", + linear: "linear", +} + +function SpringSubmessage(props: { text: string; visible: boolean; visualDuration: number; bounce: number }) { + let ref: HTMLSpanElement | undefined + let widthRef: HTMLSpanElement | undefined + + createEffect(() => { + if (!widthRef) return + if (props.visible) { + requestAnimationFrame(() => { + ref?.setAttribute("data-visible", "") + animate( + widthRef!, + { width: "auto" }, + { type: "spring", visualDuration: props.visualDuration, bounce: props.bounce }, + ) + }) + } else { + ref?.removeAttribute("data-visible") + animate( + widthRef, + { width: "0px" }, + { type: "spring", visualDuration: props.visualDuration, bounce: props.bounce }, + ) + } + }) + + return ( + + + + {props.text || "\u00A0"} + + + + ) +} + +export const Playground = { + render: () => { + const [text, setText] = createSignal("Prints five topic blocks between timed commands") + const [show, setShow] = createSignal(true) + const [visualDuration, setVisualDuration] = createSignal(0.35) + const [bounce, setBounce] = createSignal(0) + const [fadeMs, setFadeMs] = createSignal(320) + const [blur, setBlur] = createSignal(2) + const [fadeEase, setFadeEase] = createSignal("snappy") + const [auto, setAuto] = createSignal(false) + let replayTimer + let autoTimer + + const replay = () => { + setShow(false) + if (replayTimer) clearTimeout(replayTimer) + replayTimer = setTimeout(() => { + setShow(true) + }, 50) + } + + const stopAuto = () => { + if (autoTimer) clearInterval(autoTimer) + autoTimer = undefined + setAuto(false) + } + + const toggleAuto = () => { + if (auto()) { + stopAuto() + return + } + setAuto(true) + autoTimer = setInterval(replay, 2200) + } + + onCleanup(() => { + if (replayTimer) clearTimeout(replayTimer) + if (autoTimer) clearInterval(autoTimer) + }) + + return ( +
+ + + +
+ Shell + +
+
+ } + > +
+ {"$ cat <<'TOPIC1'"} +
+ + +
+ + + +
+ +
+
+ subtitle + setText(e.currentTarget.value)} + style={{ + width: "420px", + "max-width": "100%", + padding: "6px 8px", + "border-radius": "6px", + border: "1px solid var(--color-divider, #333)", + background: "var(--color-fill-element, #222)", + color: "var(--color-text, #eee)", + }} + /> +
+ +
+ visualDuration + setVisualDuration(Number(e.currentTarget.value))} + /> + {visualDuration().toFixed(2)}s +
+ +
+ bounce + setBounce(Number(e.currentTarget.value))} + /> + {bounce().toFixed(2)} +
+ +
+ fade ease + +
+ +
+ fade + setFadeMs(Number(e.currentTarget.value))} + /> + {fadeMs()}ms +
+ +
+ blur + setBlur(Number(e.currentTarget.value))} + /> + {blur()}px +
+
+
+ ) + }, +} diff --git a/packages/ui/src/components/shell-submessage.css b/packages/ui/src/components/shell-submessage.css new file mode 100644 index 0000000000..f72ba3fc75 --- /dev/null +++ b/packages/ui/src/components/shell-submessage.css @@ -0,0 +1,23 @@ +[data-component="shell-submessage"] { + min-width: 0; + max-width: 100%; + display: inline-flex; + align-items: baseline; + vertical-align: baseline; +} + +[data-component="shell-submessage"] [data-slot="shell-submessage-width"] { + min-width: 0; + max-width: 100%; + display: inline-flex; + align-items: baseline; + overflow: hidden; +} + +[data-component="shell-submessage"] [data-slot="shell-submessage-value"] { + display: inline-block; + vertical-align: baseline; + min-width: 0; + line-height: inherit; + white-space: nowrap; +} diff --git a/packages/ui/src/components/text-reveal.css b/packages/ui/src/components/text-reveal.css new file mode 100644 index 0000000000..f799962f09 --- /dev/null +++ b/packages/ui/src/components/text-reveal.css @@ -0,0 +1,150 @@ +/* + * TextReveal — mask-position wipe animation + * + * Instead of sliding text through a fixed mask (odometer style), + * the mask itself sweeps across each span to reveal/hide text. + * + * Direction: top-to-bottom. New text drops in from above, old text exits downward. + * + * Entering: gradient reveals top-to-bottom (top of text appears first). + * gradient(to bottom, white 33%, transparent 33%+edge) + * pos 0 100% = transparent covers element = hidden + * pos 0 0% = white covers element = visible + * + * Leaving: gradient hides top-to-bottom (top of text disappears first). + * gradient(to top, white 33%, transparent 33%+edge) + * pos 0 100% = white covers element = visible + * pos 0 0% = transparent covers element = hidden + * + * Both transition from 0 100% (swap) → 0 0% (settled). + */ + +[data-component="text-reveal"] { + --_edge: var(--text-reveal-edge, 17%); + --_dur: var(--text-reveal-duration, 450ms); + --_spring: var(--text-reveal-spring, cubic-bezier(0.34, 1.08, 0.64, 1)); + --_spring-soft: var(--text-reveal-spring-soft, cubic-bezier(0.34, 1, 0.64, 1)); + --_travel: var(--text-reveal-travel, 0px); + + display: inline-flex; + align-items: center; + min-width: 0; + overflow: visible; + + [data-slot="text-reveal-track"] { + display: grid; + min-height: 20px; + line-height: 20px; + justify-items: start; + align-items: center; + overflow: visible; + transition: width var(--_dur) var(--_spring-soft); + } + + [data-slot="text-reveal-entering"], + [data-slot="text-reveal-leaving"] { + grid-area: 1 / 1; + line-height: 20px; + white-space: nowrap; + justify-self: start; + text-align: start; + mask-size: 100% 300%; + -webkit-mask-size: 100% 300%; + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + transition-duration: var(--_dur); + transition-timing-function: var(--_spring); + } + + /* ── entering: reveal top-to-bottom ── + * Gradient(to top): white at bottom, transparent at top of mask. + * Settled pos 0 100% = white covers element = visible + * Swap pos 0 0% = transparent covers = hidden + * Slides from above: translateY(-travel) → translateY(0) + */ + [data-slot="text-reveal-entering"] { + mask-image: linear-gradient(to top, white 33%, transparent calc(33% + var(--_edge))); + -webkit-mask-image: linear-gradient(to top, white 33%, transparent calc(33% + var(--_edge))); + mask-position: 0 100%; + -webkit-mask-position: 0 100%; + transition-property: + mask-position, + -webkit-mask-position, + transform; + transform: translateY(0); + } + + /* ── leaving: hide top-to-bottom + slide downward ── + * Gradient(to bottom): white at top, transparent at bottom of mask. + * Swap pos 0 0% = white covers element = visible + * Settled pos 0 100% = transparent covers = hidden + * Slides down: translateY(0) → translateY(travel) + */ + [data-slot="text-reveal-leaving"] { + mask-image: linear-gradient(to bottom, white 33%, transparent calc(33% + var(--_edge))); + -webkit-mask-image: linear-gradient(to bottom, white 33%, transparent calc(33% + var(--_edge))); + mask-position: 0 100%; + -webkit-mask-position: 0 100%; + transition-property: + mask-position, + -webkit-mask-position, + transform; + transform: translateY(var(--_travel)); + } + + /* ── swapping: instant reset ── + * Snap entering to hidden (above), leaving to visible (center). + */ + &[data-swapping="true"] [data-slot="text-reveal-entering"] { + mask-position: 0 0%; + -webkit-mask-position: 0 0%; + transform: translateY(calc(var(--_travel) * -1)); + transition-duration: 0ms !important; + } + + &[data-swapping="true"] [data-slot="text-reveal-leaving"] { + mask-position: 0 0%; + -webkit-mask-position: 0 0%; + transform: translateY(0); + transition-duration: 0ms !important; + } + + /* ── not ready: kill all transitions ── */ + &[data-ready="false"] [data-slot="text-reveal-track"] { + transition-duration: 0ms !important; + } + + &[data-ready="false"] [data-slot="text-reveal-entering"], + &[data-ready="false"] [data-slot="text-reveal-leaving"] { + transition-duration: 0ms !important; + } + + &[data-truncate="true"] { + width: 100%; + } + + &[data-truncate="true"] [data-slot="text-reveal-track"] { + width: 100%; + min-width: 0; + overflow: hidden; + } + + &[data-truncate="true"] [data-slot="text-reveal-entering"], + &[data-truncate="true"] [data-slot="text-reveal-leaving"] { + min-width: 0; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + } +} + +@media (prefers-reduced-motion: reduce) { + [data-component="text-reveal"] [data-slot="text-reveal-track"] { + transition-duration: 0ms !important; + } + + [data-component="text-reveal"] [data-slot="text-reveal-entering"], + [data-component="text-reveal"] [data-slot="text-reveal-leaving"] { + transition-duration: 0ms !important; + } +} diff --git a/packages/ui/src/components/text-reveal.stories.tsx b/packages/ui/src/components/text-reveal.stories.tsx new file mode 100644 index 0000000000..df514ca38d --- /dev/null +++ b/packages/ui/src/components/text-reveal.stories.tsx @@ -0,0 +1,310 @@ +// @ts-nocheck +import { createSignal, onCleanup } from "solid-js" +import { TextReveal } from "./text-reveal" + +export default { + title: "UI/TextReveal", + id: "components-text-reveal", + tags: ["autodocs"], + parameters: { + docs: { + description: { + component: `### Overview +Playground for the TextReveal text transition component. + +**Hybrid** — mask wipe + vertical slide: gradient sweeps AND text moves downward. + +**Wipe only** — pure mask wipe: gradient sweeps top-to-bottom, text stays in place.`, + }, + }, + }, +} + +const TEXTS = [ + "Refactor ToolStatusTitle DOM measurement", + "Remove inline measure nodes", + "Run typechecks and report changes", + "Verify reduced-motion behavior", + "Review diff for animation edge cases", + "Check keyboard semantics", + undefined, + "Planning key generation details", + "Analyzing error handling", + "Considering edge cases", +] + +const btn = (accent?: boolean) => + ({ + padding: "5px 12px", + "border-radius": "6px", + border: accent ? "1px solid var(--color-accent, #58f)" : "1px solid var(--color-divider, #333)", + background: accent ? "var(--color-accent, #58f)" : "var(--color-fill-element, #222)", + color: "var(--color-text, #eee)", + cursor: "pointer", + "font-size": "12px", + }) as const + +const sliderLabel = { + width: "90px", + "font-size": "12px", + color: "var(--color-text-secondary, #a3a3a3)", + "flex-shrink": "0", +} as const + +const cardStyle = { + padding: "20px 24px", + "border-radius": "10px", + border: "1px solid var(--color-divider, #333)", + background: "var(--color-fill-element, #1a1a1a)", + display: "grid", + gap: "12px", +} as const + +const cardLabel = { + "font-size": "11px", + "font-family": "monospace", + color: "var(--color-text-weak, #666)", +} as const + +const previewRow = { + display: "flex", + "align-items": "center", + gap: "8px", + "font-size": "14px", + "font-weight": "500", + "line-height": "20px", + color: "var(--text-weak, #aaa)", + "min-height": "20px", + overflow: "visible", +} as const + +const headingSlot = { + "min-width": "0", + overflow: "visible", + color: "var(--text-weaker, #888)", + "font-weight": "400", +} as const + +export const Playground = { + render: () => { + const [index, setIndex] = createSignal(0) + const [cycling, setCycling] = createSignal(false) + const [growOnly, setGrowOnly] = createSignal(true) + + const [duration, setDuration] = createSignal(600) + const [bounce, setBounce] = createSignal(1.0) + const [bounceSoft, setBounceSoft] = createSignal(1.0) + + const [hybridTravel, setHybridTravel] = createSignal(25) + const [hybridEdge, setHybridEdge] = createSignal(17) + + const [edge, setEdge] = createSignal(17) + const [revealTravel, setRevealTravel] = createSignal(0) + + let timer: number | undefined + const text = () => TEXTS[index()] + const next = () => setIndex((i) => (i + 1) % TEXTS.length) + const prev = () => setIndex((i) => (i - 1 + TEXTS.length) % TEXTS.length) + + const toggleCycle = () => { + if (cycling()) { + if (timer) clearTimeout(timer) + timer = undefined + setCycling(false) + return + } + setCycling(true) + const tick = () => { + next() + timer = window.setTimeout(tick, 700 + Math.floor(Math.random() * 600)) + } + timer = window.setTimeout(tick, 700 + Math.floor(Math.random() * 600)) + } + + onCleanup(() => { + if (timer) clearTimeout(timer) + }) + + const spring = () => `cubic-bezier(0.34, ${bounce()}, 0.64, 1)` + const springSoft = () => `cubic-bezier(0.34, ${bounceSoft()}, 0.64, 1)` + + return ( +
+
+
+ text-reveal (mask wipe + slide) +
+ Thinking + + + +
+
+ +
+ text-reveal (mask wipe only) +
+ Thinking + + + +
+
+
+ +
+ {TEXTS.map((t, i) => ( + + ))} +
+ +
+ + + + +
+ +
+
Hybrid (wipe + slide)
+ + + + + +
Shared
+ + + + + + + +
+ Wipe only +
+ + + + +
+ +
+ text: {text() ?? "(none)"} · growOnly: {growOnly() ? "on" : "off"} +
+
+ ) + }, +} diff --git a/packages/ui/src/components/text-reveal.tsx b/packages/ui/src/components/text-reveal.tsx new file mode 100644 index 0000000000..c4fe1302f0 --- /dev/null +++ b/packages/ui/src/components/text-reveal.tsx @@ -0,0 +1,135 @@ +import { createEffect, createSignal, on, onCleanup, onMount } from "solid-js" + +const px = (value: number | string | undefined, fallback: number) => { + if (typeof value === "number") return `${value}px` + if (typeof value === "string") return value + return `${fallback}px` +} + +const ms = (value: number | string | undefined, fallback: number) => { + if (typeof value === "number") return `${value}ms` + if (typeof value === "string") return value + return `${fallback}ms` +} + +const pct = (value: number | undefined, fallback: number) => { + const v = value ?? fallback + return `${v}%` +} + +export function TextReveal(props: { + text?: string + class?: string + duration?: number | string + /** Gradient edge softness as a percentage of the mask (0 = hard wipe, 17 = soft). */ + edge?: number + /** Optional small vertical travel for entering text (px). Default 0. */ + travel?: number | string + spring?: string + springSoft?: string + growOnly?: boolean + truncate?: boolean +}) { + const [cur, setCur] = createSignal(props.text) + const [old, setOld] = createSignal() + const [width, setWidth] = createSignal("auto") + const [ready, setReady] = createSignal(false) + const [swapping, setSwapping] = createSignal(false) + let inRef: HTMLSpanElement | undefined + let outRef: HTMLSpanElement | undefined + let rootRef: HTMLSpanElement | undefined + let frame: number | undefined + + const win = () => inRef?.scrollWidth ?? 0 + const wout = () => outRef?.scrollWidth ?? 0 + + const widen = (next: number) => { + if (next <= 0) return + if (props.growOnly ?? true) { + const prev = Number.parseFloat(width()) + if (Number.isFinite(prev) && next <= prev) return + } + setWidth(`${next}px`) + } + + createEffect( + on( + () => props.text, + (next, prev) => { + if (next === prev) return + if (typeof next === "string" && typeof prev === "string" && next.startsWith(prev)) { + setCur(next) + widen(win()) + return + } + setSwapping(true) + setOld(prev) + setCur(next) + + if (typeof requestAnimationFrame !== "function") { + widen(Math.max(win(), wout())) + rootRef?.offsetHeight + setSwapping(false) + return + } + if (frame !== undefined && typeof cancelAnimationFrame === "function") cancelAnimationFrame(frame) + frame = requestAnimationFrame(() => { + widen(Math.max(win(), wout())) + rootRef?.offsetHeight + setSwapping(false) + frame = undefined + }) + }, + ), + ) + + onMount(() => { + widen(win()) + const fonts = typeof document !== "undefined" ? document.fonts : undefined + if (typeof requestAnimationFrame !== "function") { + setReady(true) + return + } + if (!fonts) { + requestAnimationFrame(() => setReady(true)) + return + } + fonts.ready.finally(() => { + widen(win()) + requestAnimationFrame(() => setReady(true)) + }) + }) + + onCleanup(() => { + if (frame === undefined || typeof cancelAnimationFrame !== "function") return + cancelAnimationFrame(frame) + }) + + return ( + + + + {cur() ?? "\u00A0"} + + + {old() ?? "\u00A0"} + + + + ) +} diff --git a/packages/ui/src/components/text-shimmer.css b/packages/ui/src/components/text-shimmer.css index 929a2d8516..f042dd2d86 100644 --- a/packages/ui/src/components/text-shimmer.css +++ b/packages/ui/src/components/text-shimmer.css @@ -1,43 +1,119 @@ [data-component="text-shimmer"] { --text-shimmer-step: 45ms; --text-shimmer-duration: 1200ms; + --text-shimmer-swap: 220ms; + --text-shimmer-index: 0; + --text-shimmer-angle: 90deg; + --text-shimmer-spread: 5.2ch; + --text-shimmer-size: 360%; + --text-shimmer-base-color: var(--text-weak); + --text-shimmer-peak-color: var(--text-strong); + --text-shimmer-sweep: linear-gradient( + var(--text-shimmer-angle), + transparent calc(50% - var(--text-shimmer-spread)), + var(--text-shimmer-peak-color) 50%, + transparent calc(50% + var(--text-shimmer-spread)) + ); + --text-shimmer-base: linear-gradient(var(--text-shimmer-base-color), var(--text-shimmer-base-color)); + + display: inline-flex; + align-items: baseline; + font: inherit; + letter-spacing: inherit; + line-height: inherit; } [data-component="text-shimmer"] [data-slot="text-shimmer-char"] { + display: inline-grid; white-space: pre; - color: inherit; + font: inherit; + letter-spacing: inherit; + line-height: inherit; } -[data-component="text-shimmer"][data-active="true"] [data-slot="text-shimmer-char"] { - animation-name: text-shimmer-char; +[data-component="text-shimmer"] [data-slot="text-shimmer-char-base"], +[data-component="text-shimmer"] [data-slot="text-shimmer-char-shimmer"] { + grid-area: 1 / 1; + white-space: pre; + transition: opacity var(--text-shimmer-swap) ease-out; + font: inherit; + letter-spacing: inherit; + line-height: inherit; +} + +[data-component="text-shimmer"] [data-slot="text-shimmer-char-base"] { + color: inherit; + opacity: 1; +} + +[data-component="text-shimmer"] [data-slot="text-shimmer-char-shimmer"] { + color: var(--text-weaker); + opacity: 0; +} + +[data-component="text-shimmer"][data-active="true"] [data-slot="text-shimmer-char-shimmer"] { + opacity: 1; +} + +[data-component="text-shimmer"] [data-slot="text-shimmer-char-shimmer"][data-run="true"] { + animation-name: text-shimmer-sweep; animation-duration: var(--text-shimmer-duration); animation-iteration-count: infinite; - animation-timing-function: ease-in-out; - animation-delay: calc(var(--text-shimmer-step) * var(--text-shimmer-index)); + animation-timing-function: linear; + animation-fill-mode: both; + animation-delay: calc(var(--text-shimmer-step) * var(--text-shimmer-index) * -1); + will-change: background-position; } -@keyframes text-shimmer-char { - 0%, +@keyframes text-shimmer-sweep { + 0% { + background-position: + 100% 0, + 0 0; + } + 100% { - color: var(--text-weaker); + background-position: + 0% 0, + 0 0; + } +} + +@supports ((-webkit-background-clip: text) or (background-clip: text)) { + [data-component="text-shimmer"] [data-slot="text-shimmer-char-shimmer"] { + color: transparent; + -webkit-text-fill-color: transparent; + background-image: var(--text-shimmer-sweep), var(--text-shimmer-base); + background-size: + var(--text-shimmer-size) 100%, + 100% 100%; + background-position: + 100% 0, + 0 0; + background-repeat: no-repeat; + -webkit-background-clip: text; + background-clip: text; } - 30% { - color: var(--text-weak); - } - - 55% { - color: var(--text-base); - } - - 75% { - color: var(--text-strong); + [data-component="text-shimmer"][data-active="true"] [data-slot="text-shimmer-char-base"] { + opacity: 0; } } @media (prefers-reduced-motion: reduce) { - [data-component="text-shimmer"] [data-slot="text-shimmer-char"] { + [data-component="text-shimmer"] [data-slot="text-shimmer-char-base"], + [data-component="text-shimmer"] [data-slot="text-shimmer-char-shimmer"] { + transition-duration: 0ms; + } + + [data-component="text-shimmer"] [data-slot="text-shimmer-char-shimmer"] { animation: none !important; color: inherit; + -webkit-text-fill-color: currentColor; + background-image: none; + } + + [data-component="text-shimmer"] [data-slot="text-shimmer-char-base"] { + opacity: 1 !important; } } diff --git a/packages/ui/src/components/text-shimmer.stories.tsx b/packages/ui/src/components/text-shimmer.stories.tsx index 4b6de34c2e..a88a7158b1 100644 --- a/packages/ui/src/components/text-shimmer.stories.tsx +++ b/packages/ui/src/components/text-shimmer.stories.tsx @@ -1,5 +1,6 @@ // @ts-nocheck import * as mod from "./text-shimmer" +import { useArgs } from "storybook/preview-api" import { create } from "../storybook/scaffold" const docs = `### Overview @@ -9,13 +10,14 @@ Use for pending states inside buttons or list rows. ### API - Required: \`text\` string. -- Optional: \`as\`, \`active\`, \`stepMs\`, \`durationMs\`. +- Optional: \`as\`, \`active\`, \`offset\`, \`class\`. ### Variants and states - Active/inactive state via \`active\`. ### Behavior -- Characters animate with staggered delays. +- Uses a moving gradient sweep clipped to text. +- \`offset\` lets multiple shimmers run out-of-phase. ### Accessibility - Uses \`aria-label\` with the full text. @@ -25,13 +27,27 @@ Use for pending states inside buttons or list rows. ` -const story = create({ title: "UI/TextShimmer", mod, args: { text: "Loading..." } }) +const defaults = { + text: "Loading...", + active: true, + class: "text-14-medium text-text-strong", + offset: 0, +} as const + +const story = create({ title: "UI/TextShimmer", mod, args: defaults }) export default { title: "UI/TextShimmer", id: "components-text-shimmer", component: story.meta.component, tags: ["autodocs"], + args: defaults, + argTypes: { + text: { control: "text" }, + class: { control: "text" }, + active: { control: "boolean" }, + offset: { control: { type: "range", min: 0, max: 80, step: 1 } }, + }, parameters: { docs: { description: { @@ -41,7 +57,32 @@ export default { }, } -export const Basic = story.Basic +export const Basic = { + args: defaults, + render: (args) => { + const [, updateArgs] = useArgs() + const reset = () => updateArgs(defaults) + return ( +
+ + +
+ ) + }, +} export const Inactive = { args: { @@ -49,11 +90,3 @@ export const Inactive = { active: false, }, } - -export const CustomTiming = { - args: { - text: "Custom timing", - stepMs: 80, - durationMs: 1800, - }, -} diff --git a/packages/ui/src/components/text-shimmer.tsx b/packages/ui/src/components/text-shimmer.tsx index 6ee4ef4020..c4c20b8e76 100644 --- a/packages/ui/src/components/text-shimmer.tsx +++ b/packages/ui/src/components/text-shimmer.tsx @@ -1,4 +1,4 @@ -import { For, createMemo, type ValidComponent } from "solid-js" +import { createEffect, createMemo, createSignal, onCleanup, type ValidComponent } from "solid-js" import { Dynamic } from "solid-js/web" export const TextShimmer = (props: { @@ -6,31 +6,56 @@ export const TextShimmer = (props: { class?: string as?: T active?: boolean - stepMs?: number - durationMs?: number + offset?: number }) => { - const chars = createMemo(() => Array.from(props.text)) - const active = () => props.active ?? true + const active = createMemo(() => props.active ?? true) + const offset = createMemo(() => props.offset ?? 0) + const [run, setRun] = createSignal(active()) + const swap = 220 + let timer: ReturnType | undefined + + createEffect(() => { + if (timer) { + clearTimeout(timer) + timer = undefined + } + + if (active()) { + setRun(true) + return + } + + timer = setTimeout(() => { + timer = undefined + setRun(false) + }, swap) + }) + + onCleanup(() => { + if (!timer) return + clearTimeout(timer) + }) return ( - - {(char, index) => ( - - )} - + + + + ) } diff --git a/packages/ui/src/components/text-strikethrough.css b/packages/ui/src/components/text-strikethrough.css new file mode 100644 index 0000000000..1be8054683 --- /dev/null +++ b/packages/ui/src/components/text-strikethrough.css @@ -0,0 +1,27 @@ +/* + * TextStrikethrough — spring-animated strikethrough line + * + * Draws a line-through from left to right using clip-path on a + * transparent-text overlay that carries the text-decoration. + * Grid stacking (grid-area: 1/1) layers the overlay on the base text. + * + * Key trick: -webkit-text-fill-color hides the glyph paint while + * keeping `color` (and therefore `currentColor` / text-decoration-color) + * set to the real inherited text color. + */ + +[data-component="text-strikethrough"] { + display: grid; +} + +[data-slot="text-strikethrough-line"] { + -webkit-text-fill-color: transparent; + text-decoration-line: line-through; + pointer-events: none; +} + +@media (prefers-reduced-motion: reduce) { + [data-slot="text-strikethrough-line"] { + clip-path: none !important; + } +} diff --git a/packages/ui/src/components/text-strikethrough.stories.tsx b/packages/ui/src/components/text-strikethrough.stories.tsx new file mode 100644 index 0000000000..b07e745534 --- /dev/null +++ b/packages/ui/src/components/text-strikethrough.stories.tsx @@ -0,0 +1,279 @@ +// @ts-nocheck +import { createEffect, createSignal, onCleanup, onMount } from "solid-js" +import { useSpring } from "./motion-spring" +import { TextStrikethrough } from "./text-strikethrough" + +const TEXT_SHORT = "Remove inline measure nodes" +const TEXT_MED = "Remove inline measure nodes and keep width morph behavior intact" +const TEXT_LONG = + "Refactor ToolStatusTitle DOM measurement to offscreen global measurer (unconstrained by timeline layout)" + +const btn = (active?: boolean) => + ({ + padding: "8px 18px", + "border-radius": "6px", + border: "1px solid var(--color-divider, #444)", + background: active ? "var(--color-accent, #58f)" : "var(--color-fill-element, #222)", + color: "var(--color-text, #eee)", + cursor: "pointer", + "font-size": "14px", + "font-weight": "500", + }) as const + +const heading = { + "font-size": "11px", + "font-weight": "600", + "text-transform": "uppercase" as const, + "letter-spacing": "0.05em", + color: "var(--text-weak, #888)", + "margin-bottom": "4px", +} + +const card = { + padding: "16px 20px", + "border-radius": "10px", + border: "1px solid var(--border-weak-base, #333)", + background: "var(--surface-base, #1a1a1a)", +} + +/* ─── Variant A: scaleX pseudo-line at 50% ─── */ +function VariantA(props: { active: boolean; text: string }) { + const progress = useSpring( + () => (props.active ? 1 : 0), + () => ({ visualDuration: 0.35, bounce: 0 }), + ) + return ( + + {props.text} + + + ) +} + +/* ─── Variant D: background-image line ─── */ +function VariantD(props: { active: boolean; text: string }) { + const progress = useSpring( + () => (props.active ? 1 : 0), + () => ({ visualDuration: 0.35, bounce: 0 }), + ) + return ( + + {props.text} + + ) +} + +/* ─── Variant E: grid stacking + clip-path (container %) ─── */ +function VariantE(props: { active: boolean; text: string }) { + const progress = useSpring( + () => (props.active ? 1 : 0), + () => ({ visualDuration: 0.35, bounce: 0 }), + ) + return ( + + {props.text} + + + ) +} + +/* ─── Variant F: grid stacking + clip-path mapped to text width ─── */ +function VariantF(props: { active: boolean; text: string }) { + const progress = useSpring( + () => (props.active ? 1 : 0), + () => ({ visualDuration: 0.35, bounce: 0 }), + ) + let baseRef: HTMLSpanElement | undefined + let containerRef: HTMLSpanElement | undefined + const [textWidth, setTextWidth] = createSignal(0) + const [containerWidth, setContainerWidth] = createSignal(0) + + const measure = () => { + if (baseRef) setTextWidth(baseRef.scrollWidth) + if (containerRef) setContainerWidth(containerRef.offsetWidth) + } + + onMount(measure) + createEffect(() => { + const el = containerRef + if (!el) return + const observer = new ResizeObserver(measure) + observer.observe(el) + onCleanup(() => observer.disconnect()) + }) + + const clipRight = () => { + const cw = containerWidth() + const tw = textWidth() + if (cw <= 0 || tw <= 0) return `${(1 - progress()) * 100}%` + const revealed = progress() * tw + const remaining = Math.max(0, cw - revealed) + return `${remaining}px` + } + + return ( + + + {props.text} + + + + ) +} + +export default { + title: "UI/Text Strikethrough", + id: "components-text-strikethrough", + tags: ["autodocs"], + parameters: { + docs: { + description: { + component: `### Animated Strikethrough Variants + +- **A** — scaleX line at 50% (single line only) +- **D** — background-image line (single line only) +- **E** — grid stacking + clip-path (container %) +- **F** — grid stacking + clip-path mapped to text width (the real component)`, + }, + }, + }, +} + +export const Playground = { + render: () => { + const [active, setActive] = createSignal(false) + const toggle = () => setActive((v) => !v) + + return ( +
+ + +
+
F — grid stacking + clip mapped to text width (THE COMPONENT)
+ +
+ +
+ +
+ +
+
F (inline) — same but just inline variants
+ +
+ +
+ +
+ +
+
E — grid stacking + clip-path (container %)
+ +
+ +
+ +
+ +
+
A — scaleX line at 50%
+ +
+ +
+ +
+
D — background-image line
+ +
+ +
+
+ ) + }, +} diff --git a/packages/ui/src/components/text-strikethrough.tsx b/packages/ui/src/components/text-strikethrough.tsx new file mode 100644 index 0000000000..211e7d44c0 --- /dev/null +++ b/packages/ui/src/components/text-strikethrough.tsx @@ -0,0 +1,85 @@ +import type { JSX } from "solid-js" +import { createEffect, createSignal, onCleanup, onMount } from "solid-js" +import { useSpring } from "./motion-spring" + +export function TextStrikethrough(props: { + /** Whether the strikethrough is active (line drawn across). */ + active: boolean + /** The text to display. Rendered twice internally (base + decoration overlay). */ + text: string + /** Spring visual duration in seconds. Default 0.35. */ + visualDuration?: number + class?: string + style?: JSX.CSSProperties +}) { + const progress = useSpring( + () => (props.active ? 1 : 0), + () => ({ visualDuration: props.visualDuration ?? 0.35, bounce: 0 }), + ) + + let baseRef: HTMLSpanElement | undefined + let containerRef: HTMLSpanElement | undefined + const [textWidth, setTextWidth] = createSignal(0) + const [containerWidth, setContainerWidth] = createSignal(0) + + const measure = () => { + if (baseRef) setTextWidth(baseRef.scrollWidth) + if (containerRef) setContainerWidth(containerRef.offsetWidth) + } + + onMount(measure) + + createEffect(() => { + const el = containerRef + if (!el) return + const observer = new ResizeObserver(measure) + observer.observe(el) + onCleanup(() => observer.disconnect()) + }) + + // Revealed pixels from left = progress * textWidth + const revealedPx = () => { + const tw = textWidth() + return tw > 0 ? progress() * tw : 0 + } + + // Overlay clip: hide everything to the right of revealed area + const overlayClip = () => { + const cw = containerWidth() + const tw = textWidth() + if (cw <= 0 || tw <= 0) return `inset(0 ${(1 - progress()) * 100}% 0 0)` + const remaining = Math.max(0, cw - revealedPx()) + return `inset(0 ${remaining}px 0 0)` + } + + // Base clip: hide everything to the left of revealed area (complementary) + const baseClip = () => { + const px = revealedPx() + if (px <= 0.5) return "none" + return `inset(0 0 0 ${px}px)` + } + + return ( + + + {props.text} + + + + ) +} diff --git a/packages/ui/src/components/thinking-heading.stories.tsx b/packages/ui/src/components/thinking-heading.stories.tsx new file mode 100644 index 0000000000..90eb7ee319 --- /dev/null +++ b/packages/ui/src/components/thinking-heading.stories.tsx @@ -0,0 +1,837 @@ +// @ts-nocheck +import { createSignal, createEffect, on, onMount, onCleanup } from "solid-js" +import { TextShimmer } from "./text-shimmer" +import { TextReveal } from "./text-reveal" + +export default { + title: "UI/ThinkingHeading", + id: "components-thinking-heading", + tags: ["autodocs"], + parameters: { + docs: { + description: { + component: `### Overview +Playground for animating the secondary heading beside "Thinking". + +Uses TextReveal for the production heading animation with tunable +duration, travel, bounce, and fade controls.`, + }, + }, + }, +} + +const HEADINGS = [ + "Planning key generation details", + "Analyzing error handling", + undefined, + "Reviewing authentication flow", + "Considering edge cases", + "Evaluating performance", + "Structuring the response", + "Checking type safety", + "Designing the API surface", + "Mapping dependencies", + "Outlining test strategy", +] + +// --------------------------------------------------------------------------- +// CSS +// +// Custom properties driven by sliders: +// --h-duration transition duration (e.g. "600ms") +// --h-duration-raw unitless number for calc (e.g. "600") +// --h-blur blur radius (e.g. "4px") +// --h-travel vertical travel distance (e.g. "18px") +// --h-spring full cubic-bezier for movement (set from bounce slider) +// --h-spring-soft softer version for width transitions +// --h-mask-size fade depth at top/bottom of odometer mask +// --h-mask-pad base padding-block on odometer track +// --h-mask-height extra vertical mask area per side +// --h-mask-bg background color for fade overlays +// --------------------------------------------------------------------------- + +const STYLES = ` +/* ── shared base ────────────────────────────────────────────────── */ +[data-variant] { + display: inline-flex; + align-items: center; +} + +[data-variant] [data-slot="track"] { + display: grid; + overflow: visible; + min-height: 20px; + justify-items: start; + align-items: center; + transition: width var(--h-duration, 600ms) var(--h-spring-soft, cubic-bezier(0.34, 1.1, 0.64, 1)); +} + +[data-variant] [data-slot="entering"], +[data-variant] [data-slot="leaving"] { + grid-area: 1 / 1; + line-height: 20px; + white-space: nowrap; + justify-self: start; +} + +/* kill transitions before fonts are ready */ +[data-variant][data-ready="false"] [data-slot="track"], +[data-variant][data-ready="false"] [data-slot="entering"], +[data-variant][data-ready="false"] [data-slot="leaving"] { + transition-duration: 0ms !important; +} + + +/* ── 1. spring-up ───────────────────────────────────────────────── * + * New text rises from below, old text exits upward. */ + +[data-variant="spring-up"] [data-slot="entering"], +[data-variant="spring-up"] [data-slot="leaving"] { + transition-property: transform, opacity, filter; + transition-duration: + var(--h-duration, 600ms), + calc(var(--h-duration-raw, 600) * 0.6 * 1ms), + calc(var(--h-duration-raw, 600) * 0.5 * 1ms); + transition-timing-function: var(--h-spring), ease-out, ease-out; +} +[data-variant="spring-up"] [data-slot="entering"] { + transform: translateY(0); + opacity: 1; + filter: blur(0); +} +[data-variant="spring-up"] [data-slot="leaving"] { + transform: translateY(calc(var(--h-travel, 18px) * -1)); + opacity: 0; + filter: blur(var(--h-blur, 0px)); +} +[data-variant="spring-up"][data-swapping="true"] [data-slot="entering"] { + transform: translateY(var(--h-travel, 18px)); + opacity: 0; + filter: blur(var(--h-blur, 0px)); + transition-duration: 0ms !important; +} +[data-variant="spring-up"][data-swapping="true"] [data-slot="leaving"] { + transform: translateY(0); + opacity: 1; + filter: blur(0); + transition-duration: 0ms !important; +} + + +/* ── 2. spring-down ─────────────────────────────────────────────── * + * New text drops from above, old text exits downward. */ + +[data-variant="spring-down"] [data-slot="entering"], +[data-variant="spring-down"] [data-slot="leaving"] { + transition-property: transform, opacity, filter; + transition-duration: + var(--h-duration, 600ms), + calc(var(--h-duration-raw, 600) * 0.6 * 1ms), + calc(var(--h-duration-raw, 600) * 0.5 * 1ms); + transition-timing-function: var(--h-spring), ease-out, ease-out; +} +[data-variant="spring-down"] [data-slot="entering"] { + transform: translateY(0); + opacity: 1; + filter: blur(0); +} +[data-variant="spring-down"] [data-slot="leaving"] { + transform: translateY(var(--h-travel, 18px)); + opacity: 0; + filter: blur(var(--h-blur, 0px)); +} +[data-variant="spring-down"][data-swapping="true"] [data-slot="entering"] { + transform: translateY(calc(var(--h-travel, 18px) * -1)); + opacity: 0; + filter: blur(var(--h-blur, 0px)); + transition-duration: 0ms !important; +} +[data-variant="spring-down"][data-swapping="true"] [data-slot="leaving"] { + transform: translateY(0); + opacity: 1; + filter: blur(0); + transition-duration: 0ms !important; +} + + +/* ── 3. spring-pop ──────────────────────────────────────────────── * + * Scale + slight vertical shift + blur. Playful, bouncy. */ + +[data-variant="spring-pop"] [data-slot="entering"], +[data-variant="spring-pop"] [data-slot="leaving"] { + transition-property: transform, opacity, filter; + transition-duration: + var(--h-duration, 600ms), + calc(var(--h-duration-raw, 600) * 0.55 * 1ms), + calc(var(--h-duration-raw, 600) * 0.55 * 1ms); + transition-timing-function: var(--h-spring), ease-out, ease-out; + transform-origin: left center; +} +[data-variant="spring-pop"] [data-slot="entering"] { + transform: translateY(0) scale(1); + opacity: 1; + filter: blur(0); +} +[data-variant="spring-pop"] [data-slot="leaving"] { + transform: translateY(calc(var(--h-travel, 18px) * -0.35)) scale(0.92); + opacity: 0; + filter: blur(var(--h-blur, 3px)); +} +[data-variant="spring-pop"][data-swapping="true"] [data-slot="entering"] { + transform: translateY(calc(var(--h-travel, 18px) * 0.35)) scale(0.92); + opacity: 0; + filter: blur(var(--h-blur, 3px)); + transition-duration: 0ms !important; +} +[data-variant="spring-pop"][data-swapping="true"] [data-slot="leaving"] { + transform: translateY(0) scale(1); + opacity: 1; + filter: blur(0); + transition-duration: 0ms !important; +} + + +/* ── 4. spring-blur ─────────────────────────────────────────────── * + * Pure crossfade with heavy blur. No vertical movement. * + * Width still animates with spring. */ + +[data-variant="spring-blur"] [data-slot="entering"], +[data-variant="spring-blur"] [data-slot="leaving"] { + transition-property: opacity, filter; + transition-duration: + calc(var(--h-duration-raw, 600) * 0.75 * 1ms), + var(--h-duration, 600ms); + transition-timing-function: ease-out, var(--h-spring-soft); +} +[data-variant="spring-blur"] [data-slot="entering"] { + opacity: 1; + filter: blur(0); +} +[data-variant="spring-blur"] [data-slot="leaving"] { + opacity: 0; + filter: blur(calc(var(--h-blur, 4px) * 2)); +} +[data-variant="spring-blur"][data-swapping="true"] [data-slot="entering"] { + opacity: 0; + filter: blur(calc(var(--h-blur, 4px) * 2)); + transition-duration: 0ms !important; +} +[data-variant="spring-blur"][data-swapping="true"] [data-slot="leaving"] { + opacity: 1; + filter: blur(0); + transition-duration: 0ms !important; +} + + +/* ── 5. odometer ──────────────────────────────────────────────── * + * Both texts scroll vertically through a clipped track. * + * * + * overflow:hidden clips at the padding-box edge. * + * mask-image fades to transparent at that same edge. * + * Result: content is invisible at the clip boundary → no hard * + * edge ever visible. Padding + mask height extend the clip area * + * so text has room to travel through the gradient fade zone. * + * * + * Uses transparent→white which works in both alpha & luminance * + * mask modes (transparent=hidden, white=visible in both). */ + +[data-variant="odometer"] [data-slot="track"] { + --h-mask-stop: min(var(--h-mask-size, 20px), calc(50% - 0.5px)); + --h-odo-shift: calc( + 100% + var(--h-travel, 18px) + var(--h-mask-height, 0px) + max(calc(var(--h-mask-pad, 28px) - 28px), 0px) + ); + position: relative; + align-items: stretch; + overflow: hidden; + padding-block: calc(var(--h-mask-pad, 28px) + var(--h-mask-height, 0px)); + margin-block: calc((var(--h-mask-pad, 28px) + var(--h-mask-height, 0px)) * -1); + -webkit-mask-image: linear-gradient( + to bottom, + transparent 0px, + white var(--h-mask-stop), + white calc(100% - var(--h-mask-stop)), + transparent 100% + ); + mask-image: linear-gradient( + to bottom, + transparent 0px, + white var(--h-mask-stop), + white calc(100% - var(--h-mask-stop)), + transparent 100% + ); + transition: width var(--h-duration, 600ms) var(--h-spring-soft, cubic-bezier(0.34, 1.1, 0.64, 1)); +} + +/* on swap, jump width instantly to the max of both texts */ +[data-variant="odometer"][data-swapping="true"] [data-slot="track"] { + transition-duration: 0ms !important; +} + +[data-variant="odometer"] [data-slot="entering"], +[data-variant="odometer"] [data-slot="leaving"] { + transition-property: transform; + transition-duration: var(--h-duration, 600ms); + transition-timing-function: var(--h-spring); + opacity: 1; +} +/* settled: entering in view, leaving pushed below */ +[data-variant="odometer"] [data-slot="entering"] { + transform: translateY(0); +} +[data-variant="odometer"] [data-slot="leaving"] { + transform: translateY(var(--h-odo-shift)); +} +/* swapping: snap entering above, leaving in-place */ +[data-variant="odometer"][data-swapping="true"] [data-slot="entering"] { + transform: translateY(calc(var(--h-odo-shift) * -1)); + transition-duration: 0ms !important; +} +[data-variant="odometer"][data-swapping="true"] [data-slot="leaving"] { + transform: translateY(0); + transition-duration: 0ms !important; +} + +/* ── odometer + blur ──────────────────────────────────────────── * + * Optional: adds opacity + blur transitions on top of the * + * positional odometer movement. */ + +[data-variant="odometer"][data-odo-blur="true"] [data-slot="entering"], +[data-variant="odometer"][data-odo-blur="true"] [data-slot="leaving"] { + transition-property: transform, opacity, filter; + transition-duration: + var(--h-duration, 600ms), + calc(var(--h-duration-raw, 600) * 0.6 * 1ms), + calc(var(--h-duration-raw, 600) * 0.5 * 1ms); +} +[data-variant="odometer"][data-odo-blur="true"] [data-slot="entering"] { + opacity: 1; + filter: blur(0); +} +[data-variant="odometer"][data-odo-blur="true"] [data-slot="leaving"] { + opacity: 0; + filter: blur(var(--h-blur, 4px)); +} +[data-variant="odometer"][data-odo-blur="true"][data-swapping="true"] [data-slot="entering"] { + opacity: 0; + filter: blur(var(--h-blur, 4px)); +} +[data-variant="odometer"][data-odo-blur="true"][data-swapping="true"] [data-slot="leaving"] { + opacity: 1; + filter: blur(0); +} + +/* ── debug: show fade zones ───────────────────────────────────── */ +[data-variant="odometer"][data-debug="true"] [data-slot="track"] { + outline: 1px dashed rgba(255, 0, 0, 0.6); +} +[data-variant="odometer"][data-debug="true"] [data-slot="track"]::before, +[data-variant="odometer"][data-debug="true"] [data-slot="track"]::after { + content: ""; + position: absolute; + left: 0; + right: 0; + height: var(--h-mask-stop); + pointer-events: none; +} +[data-variant="odometer"][data-debug="true"] [data-slot="track"]::before { + top: 0; + background: linear-gradient(to bottom, rgba(255, 0, 0, 0.3), transparent); +} +[data-variant="odometer"][data-debug="true"] [data-slot="track"]::after { + bottom: 0; + background: linear-gradient(to top, rgba(255, 0, 0, 0.3), transparent); +} + + +/* ── slider styling ─────────────────────────────────────────────── */ +input[type="range"].heading-slider { + -webkit-appearance: none; + appearance: none; + width: 140px; + height: 4px; + border-radius: 2px; + background: var(--color-divider, #444); + outline: none; +} +input[type="range"].heading-slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 14px; + height: 14px; + border-radius: 50%; + background: var(--color-accent, #58f); + cursor: pointer; + border: none; +} +` + +// --------------------------------------------------------------------------- +// Animated heading component +// +// Width is measured via scrollWidth (NOT Range.getBoundingClientRect) because +// getBoundingClientRect includes CSS transforms — so scale(0.92) during the +// swap phase would measure 92% of the real width and permanently clip text. +// scrollWidth returns the layout/intrinsic width, unaffected by transforms. +// --------------------------------------------------------------------------- + +function AnimatedHeading(props) { + const [current, setCurrent] = createSignal(props.text) + const [leaving, setLeaving] = createSignal(undefined) + const [width, setWidth] = createSignal("auto") + const [ready, setReady] = createSignal(false) + const [swapping, setSwapping] = createSignal(false) + let enterRef + let leaveRef + let containerRef + let frame + + const measureEnter = () => enterRef?.scrollWidth ?? 0 + const measureLeave = () => leaveRef?.scrollWidth ?? 0 + const widen = (px) => { + if (px <= 0) return + const w = Number.parseFloat(width()) + if (Number.isFinite(w) && px <= w) return + setWidth(`${px}px`) + } + + const measure = () => { + if (!current()) { + setWidth("0px") + return + } + const px = measureEnter() + if (px > 0) setWidth(`${px}px`) + } + + createEffect( + on( + () => props.text, + (next, prev) => { + if (next === prev) return + setSwapping(true) + setLeaving(prev) + setCurrent(next) + + if (frame) cancelAnimationFrame(frame) + frame = requestAnimationFrame(() => { + // For odometer keep width as a grow-only max so heading never shrinks. + if (props.variant === "odometer") { + const enterW = measureEnter() + const leaveW = measureLeave() + widen(Math.max(enterW, leaveW)) + containerRef?.offsetHeight // reflow with max width + swap positions + setSwapping(false) + } else { + containerRef?.offsetHeight + setSwapping(false) + measure() + } + frame = undefined + }) + }, + ), + ) + + onMount(() => { + measure() + document.fonts?.ready.finally(() => { + measure() + requestAnimationFrame(() => setReady(true)) + }) + }) + + onCleanup(() => { + if (frame) cancelAnimationFrame(frame) + }) + + return ( + + + + {current() ?? "\u00A0"} + + + {leaving() ?? "\u00A0"} + + + + ) +} + +// --------------------------------------------------------------------------- +// Button / layout styles +// --------------------------------------------------------------------------- + +const btn = (accent) => ({ + padding: "6px 14px", + "border-radius": "6px", + border: "1px solid var(--color-divider, #333)", + background: accent ? "var(--color-danger-fill, #c33)" : "var(--color-fill-element, #222)", + color: "var(--color-text, #eee)", + cursor: "pointer", + "font-size": "13px", +}) + +const smallBtn = (active) => ({ + padding: "4px 12px", + "border-radius": "6px", + border: active ? "1px solid var(--color-accent, #58f)" : "1px solid var(--color-divider, #333)", + background: active ? "var(--color-accent, #58f)" : "var(--color-fill-element, #222)", + color: "var(--color-text, #eee)", + cursor: "pointer", + "font-size": "12px", +}) + +const sliderLabel = { + "font-size": "11px", + "font-family": "monospace", + color: "var(--color-text-weak, #666)", + "min-width": "70px", + "flex-shrink": "0", + "text-align": "right", +} + +const sliderValue = { + "font-family": "monospace", + "font-size": "11px", + color: "var(--color-text-weak, #aaa)", + "min-width": "60px", +} + +const cardLabel = { + "font-size": "11px", + "font-family": "monospace", + color: "var(--color-text-weak, #666)", +} + +const thinkingRow = { + display: "flex", + "align-items": "center", + gap: "8px", + "min-width": "0", + "font-size": "14px", + "font-weight": "500", + "line-height": "20px", + "min-height": "20px", + color: "var(--text-weak, #aaa)", +} + +const headingSlot = { + "min-width": "0", + overflow: "visible", + "white-space": "nowrap", + color: "var(--text-weaker, #888)", + "font-weight": "400", +} + +const cardStyle = { + padding: "16px 20px", + "border-radius": "10px", + border: "1px solid var(--color-divider, #333)", + background: "var(--h-mask-bg, #1a1a1a)", + display: "grid", + gap: "8px", +} + +// --------------------------------------------------------------------------- +// Variants +// --------------------------------------------------------------------------- + +const VARIANTS: { key: string; label: string }[] = [] + +// --------------------------------------------------------------------------- +// Story +// --------------------------------------------------------------------------- + +export const Playground = { + render: () => { + const [heading, setHeading] = createSignal(HEADINGS[0]) + const [headingIndex, setHeadingIndex] = createSignal(0) + const [active, setActive] = createSignal(true) + const [cycling, setCycling] = createSignal(false) + let cycleTimer + + // tunable params + const [duration, setDuration] = createSignal(550) + const [blur, setBlur] = createSignal(2) + const [travel, setTravel] = createSignal(4) + const [bounce, setBounce] = createSignal(1.35) + const [maskSize, setMaskSize] = createSignal(12) + const [maskPad, setMaskPad] = createSignal(9) + const [maskHeight, setMaskHeight] = createSignal(0) + const [debug, setDebug] = createSignal(false) + const [odoBlur, setOdoBlur] = createSignal(false) + + const nextHeading = () => { + setHeadingIndex((i) => { + const next = (i + 1) % HEADINGS.length + setHeading(HEADINGS[next]) + return next + }) + } + + const prevHeading = () => { + setHeadingIndex((i) => { + const prev = (i - 1 + HEADINGS.length) % HEADINGS.length + setHeading(HEADINGS[prev]) + return prev + }) + } + + const toggleCycling = () => { + if (cycling()) { + clearTimeout(cycleTimer) + cycleTimer = undefined + setCycling(false) + return + } + setCycling(true) + const tick = () => { + if (!cycling()) return + nextHeading() + cycleTimer = setTimeout(tick, 850 + Math.floor(Math.random() * 550)) + } + cycleTimer = setTimeout(tick, 850 + Math.floor(Math.random() * 550)) + } + + const clearHeading = () => { + setHeading(undefined) + if (cycling()) { + clearTimeout(cycleTimer) + cycleTimer = undefined + setCycling(false) + } + } + + onCleanup(() => { + if (cycleTimer) clearTimeout(cycleTimer) + }) + + const vars = () => ({ + "--h-duration": `${duration()}ms`, + "--h-duration-raw": `${duration()}`, + "--h-blur": `${blur()}px`, + "--h-travel": `${travel()}px`, + "--h-spring": `cubic-bezier(0.34, ${bounce()}, 0.64, 1)`, + "--h-spring-soft": `cubic-bezier(0.34, ${Math.max(bounce() * 0.7, 1)}, 0.64, 1)`, + "--h-mask-size": `${maskSize()}px`, + "--h-mask-pad": `${maskPad()}px`, + "--h-mask-height": `${maskHeight()}px`, + "--h-mask-bg": "#1a1a1a", + }) + + return ( +
+ + + {/* ── Variant cards ─────────────────────────────────── */} +
+
+ TextReveal (production) + + + + + + +
+ {VARIANTS.map((v) => ( +
+ {v.label} + + + + + + +
+ ))} +
+ + {/* ── Sliders ──────────────────────────────────────── */} +
+
+ duration + setDuration(Number(e.currentTarget.value))} + /> + {duration()}ms +
+ +
+ blur + setBlur(Number(e.currentTarget.value))} + /> + {blur()}px +
+ +
+ travel + setTravel(Number(e.currentTarget.value))} + /> + {travel()}px +
+ +
+ bounce + setBounce(Number(e.currentTarget.value))} + /> + + {bounce().toFixed(2)} {bounce() <= 1.05 ? "(none)" : bounce() >= 1.9 ? "(heavy)" : ""} + +
+ +
+ mask + setMaskSize(Number(e.currentTarget.value))} + /> + + {maskSize()}px {maskSize() === 0 ? "(hard)" : ""} + +
+ +
+ mask pad + setMaskPad(Number(e.currentTarget.value))} + /> + {maskPad()}px +
+ +
+ mask height + setMaskHeight(Number(e.currentTarget.value))} + /> + {maskHeight()}px +
+
+ + {/* ── Controls ─────────────────────────────────────── */} +
+
+ + + + + + + +
+ +
+ {HEADINGS.map((h, i) => ( + + ))} +
+ +
+ heading: {heading() ?? "(none)"} · sim: {cycling() ? "on" : "off"} · bounce: {bounce().toFixed(2)} · + odo-blur: {odoBlur() ? "on" : "off"} +
+
+
+ ) + }, +} diff --git a/packages/ui/src/components/todo-panel-motion.stories.tsx b/packages/ui/src/components/todo-panel-motion.stories.tsx new file mode 100644 index 0000000000..39d3421578 --- /dev/null +++ b/packages/ui/src/components/todo-panel-motion.stories.tsx @@ -0,0 +1,584 @@ +// @ts-nocheck +import { createEffect, createMemo, createSignal, onCleanup } from "solid-js" +import type { Todo } from "@opencode-ai/sdk/v2" +import { useGlobalSync } from "@/context/global-sync" +import { SessionComposerRegion, createSessionComposerState } from "@/pages/session/composer" + +export default { + title: "UI/Todo Panel Motion", + id: "components-todo-panel-motion", + tags: ["autodocs"], + parameters: { + docs: { + description: { + component: `### Overview +This playground renders the real session composer region from app code. + +### Source path +- \`packages/app/src/pages/session/composer/session-composer-region.tsx\` + +### Includes +- \`SessionTodoDock\` (real) +- \`PromptInput\` (real) + +No visual reimplementation layer is used for the dock/input stack.`, + }, + }, + }, +} + +const pool = [ + "Refactor ToolStatusTitle DOM measurement to offscreen global measurer (unconstrained by timeline layout)", + "Remove inline measure nodes/CSS hooks and keep width morph behavior intact", + "Run typechecks/tests and report what changed", + "Verify reduced-motion behavior in timeline", + "Review diff for animation edge cases", + "Document rollout notes in PR description", + "Check keyboard and screen reader semantics", + "Add storybook controls for iteration speed", +] + +const btn = (accent?: boolean) => + ({ + padding: "6px 14px", + "border-radius": "6px", + border: "1px solid var(--color-divider, #333)", + background: accent ? "var(--color-accent, #58f)" : "var(--color-fill-element, #222)", + color: "var(--color-text, #eee)", + cursor: "pointer", + "font-size": "13px", + }) as const + +const css = ` +[data-component="todo-stage"] { + display: grid; + gap: 20px; + padding: 20px; +} + +[data-component="todo-preview"] { + height: 560px; + min-height: 0; +} + +[data-component="todo-session-root"] { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; + display: flex; + flex-direction: column; + background: var(--background-base); + border: 1px solid var(--border-weak-base); + border-radius: 12px; +} + +[data-component="todo-session-frame"] { + flex: 1 1 auto; + min-height: 0; + display: flex; + flex-direction: column; +} + +[data-component="todo-session-panel"] { + position: relative; + flex: 1 1 auto; + min-height: 0; + height: 100%; + display: flex; + flex-direction: column; + background: var(--background-stronger); +} + +[data-slot="todo-preview-content"] { + flex: 1 1 auto; + min-height: 0; + overflow: hidden; +} + +[data-slot="todo-preview-scroll"] { + height: 100%; + overflow: auto; + min-height: 0; + padding: 14px 16px; + display: flex; + flex-direction: column; + gap: 10px; +} + +[data-slot="todo-preview-spacer"] { + flex: 1 1 auto; + min-height: 0; +} + +[data-slot="todo-preview-msg"] { + border-radius: 8px; + border: 1px solid var(--border-weak-base); + background: var(--surface-base); + color: var(--text-weak); + padding: 8px 10px; + font-size: 13px; + line-height: 1.35; +} + +[data-slot="todo-preview-msg"][data-strong="true"] { + color: var(--text-strong); +} +` + +export const Playground = { + render: () => { + const global = useGlobalSync() + const [open, setOpen] = createSignal(true) + const [step, setStep] = createSignal(1) + const [dockOpenDuration, setDockOpenDuration] = createSignal(0.3) + const [dockOpenBounce, setDockOpenBounce] = createSignal(0) + const [dockCloseDuration, setDockCloseDuration] = createSignal(0.3) + const [dockCloseBounce, setDockCloseBounce] = createSignal(0) + const [drawerExpandDuration, setDrawerExpandDuration] = createSignal(0.3) + const [drawerExpandBounce, setDrawerExpandBounce] = createSignal(0) + const [drawerCollapseDuration, setDrawerCollapseDuration] = createSignal(0.3) + const [drawerCollapseBounce, setDrawerCollapseBounce] = createSignal(0) + const [subtitleDuration, setSubtitleDuration] = createSignal(600) + const [subtitleAuto, setSubtitleAuto] = createSignal(true) + const [subtitleTravel, setSubtitleTravel] = createSignal(25) + const [subtitleEdge, setSubtitleEdge] = createSignal(17) + const [countDuration, setCountDuration] = createSignal(600) + const [countMask, setCountMask] = createSignal(18) + const [countMaskHeight, setCountMaskHeight] = createSignal(0) + const [countWidthDuration, setCountWidthDuration] = createSignal(560) + const state = createSessionComposerState({ closeMs: () => Math.round(dockCloseDuration() * 1000) }) + let frame + let composerRef + let scrollRef + + const todos = createMemo(() => { + const done = Math.max(0, Math.min(3, step())) + return pool.slice(0, 3).map((content, i) => ({ + id: `todo-${i + 1}`, + content, + status: i < done ? "completed" : i === done && done < 3 ? "in_progress" : "pending", + })) + }) + + createEffect(() => { + global.todo.set("story-session", todos()) + }) + + const clear = () => { + if (frame) cancelAnimationFrame(frame) + frame = undefined + } + + const pin = () => { + if (!scrollRef) return + scrollRef.scrollTop = scrollRef.scrollHeight + } + + const collapsed = () => + !!composerRef?.querySelector('[data-action="session-todo-toggle-button"][data-collapsed="true"]') + + const setCollapsed = (value: boolean) => { + const button = composerRef?.querySelector('[data-action="session-todo-toggle-button"]') + if (!(button instanceof HTMLButtonElement)) return + if (collapsed() === value) return + button.click() + } + + const openDock = () => { + clear() + setOpen(true) + frame = requestAnimationFrame(() => { + pin() + frame = undefined + }) + } + + const closeDock = () => { + clear() + setOpen(false) + } + + const dockOpen = () => open() + + const toggleDock = () => { + if (dockOpen()) { + closeDock() + return + } + openDock() + } + + const toggleDrawer = () => { + if (!dockOpen()) { + openDock() + frame = requestAnimationFrame(() => { + pin() + setCollapsed(true) + frame = undefined + }) + return + } + setCollapsed(!collapsed()) + } + + const cycle = () => { + setStep((value) => (value + 1) % 4) + } + + onCleanup(clear) + + return ( +
+ + +
+
+
+
+
+
+
+
+ Thinking Checking type safety +
+
Shell Prints five topic blocks between timed commands
+
+
+ +
+ {}} + newSessionWorktree="" + onNewSessionWorktreeReset={() => {}} + onSubmit={() => {}} + onResponseSubmit={pin} + setPromptDockRef={() => {}} + dockOpenVisualDuration={dockOpenDuration()} + dockOpenBounce={dockOpenBounce()} + dockCloseVisualDuration={dockCloseDuration()} + dockCloseBounce={dockCloseBounce()} + drawerExpandVisualDuration={drawerExpandDuration()} + drawerExpandBounce={drawerExpandBounce()} + drawerCollapseVisualDuration={drawerCollapseDuration()} + drawerCollapseBounce={drawerCollapseBounce()} + subtitleDuration={subtitleDuration()} + subtitleTravel={subtitleAuto() ? undefined : subtitleTravel()} + subtitleEdge={subtitleAuto() ? undefined : subtitleEdge()} + countDuration={countDuration()} + countMask={countMask()} + countMaskHeight={countMaskHeight()} + countWidthDuration={countWidthDuration()} + /> +
+
+
+
+
+ +
+ + + + {[0, 1, 2, 3].map((value) => ( + + ))} +
+ +
+
Dock open
+ + + +
+ Dock close +
+ + + +
+ Drawer expand +
+ + + +
+ Drawer collapse +
+ + + +
+ Subtitle odometer +
+ + + + + +
+ Count odometer +
+ + + + +
+
+ ) + }, +} diff --git a/packages/ui/src/components/tool-count-label.css b/packages/ui/src/components/tool-count-label.css new file mode 100644 index 0000000000..11a33ff5d1 --- /dev/null +++ b/packages/ui/src/components/tool-count-label.css @@ -0,0 +1,57 @@ +[data-component="tool-count-label"] { + display: inline-flex; + align-items: baseline; + white-space: nowrap; + gap: 0; + + [data-slot="tool-count-label-before"] { + display: inline-block; + white-space: pre; + line-height: inherit; + } + + [data-slot="tool-count-label-word"] { + display: inline-flex; + align-items: baseline; + white-space: pre; + line-height: inherit; + } + + [data-slot="tool-count-label-stem"] { + display: inline-block; + white-space: pre; + } + + [data-slot="tool-count-label-suffix"] { + display: inline-grid; + grid-template-columns: 0fr; + opacity: 0; + filter: blur(calc(var(--tool-motion-blur, 2px) * 0.42)); + overflow: hidden; + transform: translateX(-0.04em); + transition-property: grid-template-columns, opacity, filter, transform; + transition-duration: 250ms, 250ms, 250ms, 250ms; + transition-timing-function: + var(--tool-motion-ease, cubic-bezier(0.22, 1, 0.36, 1)), ease-out, ease-out, + var(--tool-motion-ease, cubic-bezier(0.22, 1, 0.36, 1)); + } + + [data-slot="tool-count-label-suffix"][data-active="true"] { + grid-template-columns: 1fr; + opacity: 1; + filter: blur(0); + transform: translateX(0); + } + + [data-slot="tool-count-label-suffix-inner"] { + min-width: 0; + overflow: hidden; + white-space: pre; + } +} + +@media (prefers-reduced-motion: reduce) { + [data-component="tool-count-label"] [data-slot="tool-count-label-suffix"] { + transition-duration: 0ms; + } +} diff --git a/packages/ui/src/components/tool-count-label.tsx b/packages/ui/src/components/tool-count-label.tsx new file mode 100644 index 0000000000..67e861cdcb --- /dev/null +++ b/packages/ui/src/components/tool-count-label.tsx @@ -0,0 +1,58 @@ +import { createMemo } from "solid-js" +import { AnimatedNumber } from "./animated-number" + +function split(text: string) { + const match = /{{\s*count\s*}}/.exec(text) + if (!match) return { before: "", after: text } + if (match.index === undefined) return { before: "", after: text } + return { + before: text.slice(0, match.index), + after: text.slice(match.index + match[0].length), + } +} + +function common(one: string, other: string) { + const a = Array.from(one) + const b = Array.from(other) + let i = 0 + while (i < a.length && i < b.length && a[i] === b[i]) i++ + return { + stem: a.slice(0, i).join(""), + one: a.slice(i).join(""), + other: b.slice(i).join(""), + } +} + +export function AnimatedCountLabel(props: { count: number; one: string; other: string; class?: string }) { + const one = createMemo(() => split(props.one)) + const other = createMemo(() => split(props.other)) + const singular = createMemo(() => Math.round(props.count) === 1) + const active = createMemo(() => (singular() ? one() : other())) + const suffix = createMemo(() => common(one().after, other().after)) + const splitSuffix = createMemo( + () => + one().before === other().before && + (one().after.startsWith(other().after) || other().after.startsWith(one().after)), + ) + const before = createMemo(() => (splitSuffix() ? one().before : active().before)) + const stem = createMemo(() => (splitSuffix() ? suffix().stem : active().after)) + const tail = createMemo(() => { + if (!splitSuffix()) return "" + if (singular()) return suffix().one + return suffix().other + }) + const showTail = createMemo(() => splitSuffix() && tail().length > 0) + + return ( + + {before()} + + + {stem()} + + {tail()} + + + + ) +} diff --git a/packages/ui/src/components/tool-count-summary.css b/packages/ui/src/components/tool-count-summary.css new file mode 100644 index 0000000000..da8455267c --- /dev/null +++ b/packages/ui/src/components/tool-count-summary.css @@ -0,0 +1,102 @@ +[data-component="tool-count-summary"] { + display: inline-flex; + align-items: baseline; + white-space: nowrap; + + [data-slot="tool-count-summary-empty"] { + display: inline-grid; + grid-template-columns: 1fr; + align-items: baseline; + opacity: 1; + filter: blur(0); + transform: translateY(0) scale(1); + overflow: hidden; + transform-origin: left center; + transition-property: grid-template-columns, opacity, filter, transform; + transition-duration: + var(--tool-motion-spring-ms, 480ms), var(--tool-motion-fade-ms, 240ms), var(--tool-motion-fade-ms, 280ms), + var(--tool-motion-spring-ms, 480ms); + transition-timing-function: + var(--tool-motion-ease, cubic-bezier(0.22, 1, 0.36, 1)), ease-out, ease-out, + var(--tool-motion-ease, cubic-bezier(0.22, 1, 0.36, 1)); + } + + [data-slot="tool-count-summary-empty"][data-active="false"] { + grid-template-columns: 0fr; + opacity: 0; + filter: blur(calc(var(--tool-motion-blur, 2px) * 0.72)); + transform: translateY(0.05em) scale(0.985); + } + + [data-slot="tool-count-summary-item"] { + display: inline-grid; + grid-template-columns: 0fr; + align-items: baseline; + opacity: 0; + filter: blur(var(--tool-motion-blur, 2px)); + transform: translateY(0.06em) scale(0.985); + overflow: hidden; + transform-origin: left center; + transition-property: grid-template-columns, opacity, filter, transform; + transition-duration: + var(--tool-motion-spring-ms, 480ms), var(--tool-motion-fade-ms, 280ms), var(--tool-motion-fade-ms, 320ms), + var(--tool-motion-spring-ms, 480ms); + transition-timing-function: + var(--tool-motion-ease, cubic-bezier(0.22, 1, 0.36, 1)), ease-out, ease-out, + var(--tool-motion-ease, cubic-bezier(0.22, 1, 0.36, 1)); + } + + [data-slot="tool-count-summary-item"][data-active="true"] { + grid-template-columns: 1fr; + opacity: 1; + filter: blur(0); + transform: translateY(0) scale(1); + } + + [data-slot="tool-count-summary-empty-inner"] { + min-width: 0; + overflow: hidden; + white-space: nowrap; + } + + [data-slot="tool-count-summary-item-inner"] { + display: inline-flex; + align-items: baseline; + min-width: 0; + overflow: hidden; + white-space: nowrap; + } + + [data-slot="tool-count-summary-prefix"] { + display: inline-flex; + align-items: baseline; + justify-content: flex-start; + max-width: 0; + margin-right: 0; + opacity: 0; + filter: blur(calc(var(--tool-motion-blur, 2px) * 0.55)); + overflow: hidden; + transform: translateX(-0.08em); + transition-property: opacity, filter, transform; + transition-duration: + calc(var(--tool-motion-fade-ms, 200ms) * 0.75), calc(var(--tool-motion-fade-ms, 220ms) * 0.75), + calc(var(--tool-motion-fade-ms, 220ms) * 0.6); + transition-timing-function: ease-out, ease-out, ease-out; + } + + [data-slot="tool-count-summary-prefix"][data-active="true"] { + max-width: 1ch; + margin-right: 0.45ch; + opacity: 1; + filter: blur(0); + transform: translateX(0); + } +} + +@media (prefers-reduced-motion: reduce) { + [data-component="tool-count-summary"] [data-slot="tool-count-summary-empty"], + [data-component="tool-count-summary"] [data-slot="tool-count-summary-item"], + [data-component="tool-count-summary"] [data-slot="tool-count-summary-prefix"] { + transition-duration: 0ms; + } +} diff --git a/packages/ui/src/components/tool-count-summary.stories.tsx b/packages/ui/src/components/tool-count-summary.stories.tsx new file mode 100644 index 0000000000..4be3a02bbe --- /dev/null +++ b/packages/ui/src/components/tool-count-summary.stories.tsx @@ -0,0 +1,230 @@ +// @ts-nocheck +import { createSignal, onCleanup } from "solid-js" +import { AnimatedCountList, type CountItem } from "./tool-count-summary" +import { ToolStatusTitle } from "./tool-status-title" + +export default { + title: "UI/AnimatedCountList", + id: "components-animated-count-list", + tags: ["autodocs"], + parameters: { + docs: { + description: { + component: `### Overview +Animated count list that smoothly transitions items in/out as counts change. + +Uses \`grid-template-columns: 0fr → 1fr\` for width animations and the odometer +digit roller for count transitions. Shown here with \`ToolStatusTitle\` exactly +as it appears in the context tool group on the session page.`, + }, + }, + }, +} + +const TEXT = { + active: "Exploring", + done: "Explored", + read: { one: "{{count}} read", other: "{{count}} reads" }, + search: { one: "{{count}} search", other: "{{count}} searches" }, + list: { one: "{{count}} list", other: "{{count}} lists" }, +} as const + +function rand(min: number, max: number) { + return Math.floor(Math.random() * (max - min + 1)) + min +} + +const btn = (accent?: boolean) => + ({ + padding: "6px 14px", + "border-radius": "6px", + border: "1px solid var(--color-divider, #333)", + background: accent ? "var(--color-danger-fill, #c33)" : "var(--color-fill-element, #222)", + color: "var(--color-text, #eee)", + cursor: "pointer", + "font-size": "13px", + }) as const + +const smallBtn = (active?: boolean) => + ({ + padding: "4px 12px", + "border-radius": "6px", + border: active ? "1px solid var(--color-accent, #58f)" : "1px solid var(--color-divider, #333)", + background: active ? "var(--color-accent, #58f)" : "var(--color-fill-element, #222)", + color: "var(--color-text, #eee)", + cursor: "pointer", + "font-size": "12px", + }) as const + +export const Playground = { + render: () => { + const [reads, setReads] = createSignal(0) + const [searches, setSearches] = createSignal(0) + const [lists, setLists] = createSignal(0) + const [active, setActive] = createSignal(false) + const [reducedMotion, setReducedMotion] = createSignal(false) + + let timeouts: ReturnType[] = [] + + const clearAll = () => { + for (const t of timeouts) clearTimeout(t) + timeouts = [] + } + + onCleanup(clearAll) + + const startSim = () => { + clearAll() + setReads(0) + setSearches(0) + setLists(0) + setActive(true) + const steps = rand(3, 10) + let elapsed = 0 + + for (let i = 0; i < steps; i++) { + const delay = rand(300, 800) + elapsed += delay + const t = setTimeout(() => { + const pick = rand(0, 2) + if (pick === 0) setReads((n) => n + 1) + else if (pick === 1) setSearches((n) => n + 1) + else setLists((n) => n + 1) + }, elapsed) + timeouts.push(t) + } + + const end = setTimeout(() => setActive(false), elapsed + 100) + timeouts.push(end) + } + + const stopSim = () => { + clearAll() + setActive(false) + } + + const reset = () => { + stopSim() + setReads(0) + setSearches(0) + setLists(0) + } + + const items = (): CountItem[] => [ + { key: "read", count: reads(), one: TEXT.read.one, other: TEXT.read.other }, + { key: "search", count: searches(), one: TEXT.search.one, other: TEXT.search.other }, + { key: "list", count: lists(), one: TEXT.list.one, other: TEXT.list.other }, + ] + + return ( +
+ {reducedMotion() && ( + + )} + + {/* Matches context-tool-group-trigger layout from message-part.tsx */} + + + + + + + + + +
+ + + +
+ +
+ + + +
+ +
+ motion: {reducedMotion() ? "reduced" : "normal"} · active: {active() ? "true" : "false"} · reads: {reads()} · + searches: {searches()} · lists: {lists()} +
+
+ ) + }, +} + +export const Empty = { + render: () => ( + + + + + ), +} + +export const Done = { + render: () => ( + + + + + + + ), +} diff --git a/packages/ui/src/components/tool-count-summary.tsx b/packages/ui/src/components/tool-count-summary.tsx new file mode 100644 index 0000000000..a5cb5b40d2 --- /dev/null +++ b/packages/ui/src/components/tool-count-summary.tsx @@ -0,0 +1,52 @@ +import { Index, createMemo } from "solid-js" +import { AnimatedCountLabel } from "./tool-count-label" + +export type CountItem = { + key: string + count: number + one: string + other: string +} + +export function AnimatedCountList(props: { items: CountItem[]; fallback?: string; class?: string }) { + const visible = createMemo(() => props.items.filter((item) => item.count > 0)) + const fallback = createMemo(() => props.fallback ?? "") + const showEmpty = createMemo(() => visible().length === 0 && fallback().length > 0) + + return ( + + + {fallback()} + + + + {(item, index) => { + const active = createMemo(() => item().count > 0) + const hasPrev = createMemo(() => { + for (let i = index - 1; i >= 0; i--) { + if (props.items[i].count > 0) return true + } + return false + }) + + return ( + <> + + , + + + + + + + + ) + }} + + + ) +} diff --git a/packages/ui/src/components/tool-status-title.css b/packages/ui/src/components/tool-status-title.css new file mode 100644 index 0000000000..d4415bd2da --- /dev/null +++ b/packages/ui/src/components/tool-status-title.css @@ -0,0 +1,89 @@ +[data-component="tool-status-title"] { + display: inline-flex; + align-items: baseline; + white-space: nowrap; + text-align: start; + + [data-slot="tool-status-suffix"] { + display: inline-flex; + align-items: baseline; + white-space: nowrap; + } + + [data-slot="tool-status-prefix"] { + white-space: nowrap; + flex-shrink: 0; + } + + [data-slot="tool-status-swap"], + [data-slot="tool-status-tail"] { + display: inline-grid; + overflow: hidden; + justify-items: start; + transition: width var(--tool-motion-spring-ms, 480ms) var(--tool-motion-ease, cubic-bezier(0.22, 1, 0.36, 1)); + } + + [data-slot="tool-status-active"], + [data-slot="tool-status-done"] { + grid-area: 1 / 1; + white-space: nowrap; + justify-self: start; + text-align: start; + transition-property: opacity, filter, transform; + transition-duration: + var(--tool-motion-fade-ms, 240ms), calc(var(--tool-motion-fade-ms, 240ms) * 0.8), + calc(var(--tool-motion-fade-ms, 240ms) * 0.8); + transition-timing-function: ease-out, ease-out, ease-out; + } + + &[data-ready="false"] { + [data-slot="tool-status-swap"], + [data-slot="tool-status-tail"] { + transition-duration: 0ms; + } + + [data-slot="tool-status-active"], + [data-slot="tool-status-done"] { + transition-duration: 0ms; + } + } + + [data-slot="tool-status-active"] { + opacity: 0; + filter: blur(calc(var(--tool-motion-blur, 2px) * 0.45)); + transform: translateY(0.03em); + } + + [data-slot="tool-status-done"] { + color: var(--text-strong); + opacity: 1; + filter: blur(0); + transform: translateY(0); + } + + &[data-active="true"] { + [data-slot="tool-status-active"] { + opacity: 1; + filter: blur(0); + transform: translateY(0); + } + + [data-slot="tool-status-done"] { + opacity: 0; + filter: blur(calc(var(--tool-motion-blur, 2px) * 0.45)); + transform: translateY(0.03em); + } + } +} + +@media (prefers-reduced-motion: reduce) { + [data-component="tool-status-title"] [data-slot="tool-status-swap"], + [data-component="tool-status-title"] [data-slot="tool-status-tail"] { + transition-duration: 0ms; + } + + [data-component="tool-status-title"] [data-slot="tool-status-active"], + [data-component="tool-status-title"] [data-slot="tool-status-done"] { + transition-duration: 0ms; + } +} diff --git a/packages/ui/src/components/tool-status-title.tsx b/packages/ui/src/components/tool-status-title.tsx new file mode 100644 index 0000000000..68440b6c63 --- /dev/null +++ b/packages/ui/src/components/tool-status-title.tsx @@ -0,0 +1,133 @@ +import { Show, createEffect, createMemo, createSignal, on, onCleanup, onMount } from "solid-js" +import { TextShimmer } from "./text-shimmer" + +function common(active: string, done: string) { + const a = Array.from(active) + const b = Array.from(done) + let i = 0 + while (i < a.length && i < b.length && a[i] === b[i]) i++ + return { + prefix: a.slice(0, i).join(""), + active: a.slice(i).join(""), + done: b.slice(i).join(""), + } +} + +function contentWidth(el: HTMLSpanElement | undefined) { + if (!el) return 0 + const range = document.createRange() + range.selectNodeContents(el) + return Math.ceil(range.getBoundingClientRect().width) +} + +export function ToolStatusTitle(props: { + active: boolean + activeText: string + doneText: string + class?: string + split?: boolean +}) { + const split = createMemo(() => common(props.activeText, props.doneText)) + const suffix = createMemo( + () => (props.split ?? true) && split().prefix.length >= 2 && split().active.length > 0 && split().done.length > 0, + ) + const prefixLen = createMemo(() => Array.from(split().prefix).length) + const activeTail = createMemo(() => (suffix() ? split().active : props.activeText)) + const doneTail = createMemo(() => (suffix() ? split().done : props.doneText)) + + const [width, setWidth] = createSignal("auto") + const [ready, setReady] = createSignal(false) + let activeRef: HTMLSpanElement | undefined + let doneRef: HTMLSpanElement | undefined + let frame: number | undefined + let readyFrame: number | undefined + + const measure = () => { + const target = props.active ? activeRef : doneRef + const px = contentWidth(target) + if (px > 0) setWidth(`${px}px`) + } + + const schedule = () => { + if (typeof requestAnimationFrame !== "function") { + measure() + return + } + if (frame !== undefined) cancelAnimationFrame(frame) + frame = requestAnimationFrame(() => { + frame = undefined + measure() + }) + } + + const finish = () => { + if (typeof requestAnimationFrame !== "function") { + setReady(true) + return + } + if (readyFrame !== undefined) cancelAnimationFrame(readyFrame) + readyFrame = requestAnimationFrame(() => { + readyFrame = undefined + setReady(true) + }) + } + + createEffect(on([() => props.active, activeTail, doneTail, suffix], () => schedule())) + + onMount(() => { + measure() + const fonts = typeof document !== "undefined" ? document.fonts : undefined + if (!fonts) { + finish() + return + } + fonts.ready.finally(() => { + measure() + finish() + }) + }) + + onCleanup(() => { + if (frame !== undefined) cancelAnimationFrame(frame) + if (readyFrame !== undefined) cancelAnimationFrame(readyFrame) + }) + + return ( + + + + + + + + + + } + > + + + + + + + + + + + + + + + + ) +} diff --git a/packages/ui/src/hooks/create-auto-scroll.tsx b/packages/ui/src/hooks/create-auto-scroll.tsx index c32017739c..3dc520c621 100644 --- a/packages/ui/src/hooks/create-auto-scroll.tsx +++ b/packages/ui/src/hooks/create-auto-scroll.tsx @@ -48,14 +48,14 @@ export function createAutoScroll(options: AutoScrollOptions) { autoTimer = setTimeout(() => { auto = undefined autoTimer = undefined - }, 250) + }, 1500) } const isAuto = (el: HTMLElement) => { const a = auto if (!a) return false - if (Date.now() - a.time > 250) { + if (Date.now() - a.time > 1500) { auto = undefined return false } @@ -78,14 +78,19 @@ export function createAutoScroll(options: AutoScrollOptions) { const scrollToBottom = (force: boolean) => { if (!force && !active()) return + + if (force && store.userScrolled) setStore("userScrolled", false) + const el = scroll if (!el) return if (!force && store.userScrolled) return - if (force && store.userScrolled) setStore("userScrolled", false) const distance = distanceFromBottom(el) - if (distance < 2) return + if (distance < 2) { + markAuto(el) + return + } // For auto-following content we prefer immediate updates to avoid // visible "catch up" animations while content is still settling. @@ -142,7 +147,10 @@ export function createAutoScroll(options: AutoScrollOptions) { const handleInteraction = () => { if (!active()) return - stop() + const selection = window.getSelection() + if (selection && selection.toString().length > 0) { + stop() + } } const updateOverflowAnchor = (el: HTMLElement) => { diff --git a/packages/ui/src/i18n/ar.ts b/packages/ui/src/i18n/ar.ts index 4eb1b47556..3579eff5a8 100644 --- a/packages/ui/src/i18n/ar.ts +++ b/packages/ui/src/i18n/ar.ts @@ -40,6 +40,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "إعادة المحاولة", "ui.sessionTurn.retry.inSeconds": "خلال {{seconds}} ثواني", + "ui.sessionTurn.retry.attempt": "المحاولة رقم {{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - المحاولة رقم {{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini مزدحم حاليا", "ui.sessionTurn.error.freeUsageExceeded": "تم تجاوز حد الاستخدام المجاني", "ui.sessionTurn.error.addCredits": "إضافة رصيد", @@ -57,6 +60,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "النظر في الخطوات التالية", "ui.messagePart.questions.dismissed": "تم رفض الأسئلة", + "ui.messagePart.compaction": "تم ضغط السجل", "ui.messagePart.context.read.one": "{{count}} قراءة", "ui.messagePart.context.read.other": "{{count}} قراءات", "ui.messagePart.context.search.one": "{{count}} بحث", @@ -122,6 +126,7 @@ export const dict = { "ui.message.copyResponse": "نسخ الرد", "ui.message.copied": "تم النسخ!", "ui.message.interrupted": "تمت المقاطعة", + "ui.message.queued": "في الانتظار", "ui.message.attachment.alt": "مرفق", "ui.patch.action.deleted": "محذوف", diff --git a/packages/ui/src/i18n/br.ts b/packages/ui/src/i18n/br.ts index a2c3fb642c..76028878f9 100644 --- a/packages/ui/src/i18n/br.ts +++ b/packages/ui/src/i18n/br.ts @@ -40,6 +40,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "tentando novamente", "ui.sessionTurn.retry.inSeconds": "em {{seconds}}s", + "ui.sessionTurn.retry.attempt": "tentativa #{{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - tentativa #{{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini está muito sobrecarregado agora", "ui.sessionTurn.error.freeUsageExceeded": "Limite de uso gratuito excedido", "ui.sessionTurn.error.addCredits": "Adicionar créditos", @@ -57,6 +60,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "Considerando próximos passos", "ui.messagePart.questions.dismissed": "Perguntas descartadas", + "ui.messagePart.compaction": "Histórico compactado", "ui.messagePart.context.read.one": "{{count}} leitura", "ui.messagePart.context.read.other": "{{count}} leituras", "ui.messagePart.context.search.one": "{{count}} pesquisa", @@ -122,6 +126,7 @@ export const dict = { "ui.message.copyResponse": "Copiar resposta", "ui.message.copied": "Copiado!", "ui.message.interrupted": "Interrompido", + "ui.message.queued": "Na fila", "ui.message.attachment.alt": "anexo", "ui.patch.action.deleted": "Excluído", diff --git a/packages/ui/src/i18n/bs.ts b/packages/ui/src/i18n/bs.ts index c75e158ba3..9bc2293361 100644 --- a/packages/ui/src/i18n/bs.ts +++ b/packages/ui/src/i18n/bs.ts @@ -44,6 +44,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "ponovni pokušaj", "ui.sessionTurn.retry.inSeconds": "za {{seconds}}s", + "ui.sessionTurn.retry.attempt": "pokušaj #{{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - pokušaj #{{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini je trenutno preopterećen", "ui.sessionTurn.error.freeUsageExceeded": "Besplatna upotreba premašena", "ui.sessionTurn.error.addCredits": "Dodaj kredite", @@ -61,6 +64,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "Razmatranje sljedećih koraka", "ui.messagePart.questions.dismissed": "Pitanja odbačena", + "ui.messagePart.compaction": "Historija sažeta", "ui.messagePart.context.read.one": "{{count}} čitanje", "ui.messagePart.context.read.other": "{{count}} čitanja", "ui.messagePart.context.search.one": "{{count}} pretraga", @@ -126,6 +130,7 @@ export const dict = { "ui.message.copyResponse": "Kopiraj odgovor", "ui.message.copied": "Kopirano!", "ui.message.interrupted": "Prekinuto", + "ui.message.queued": "U redu", "ui.message.attachment.alt": "prilog", "ui.patch.action.deleted": "Obrisano", diff --git a/packages/ui/src/i18n/da.ts b/packages/ui/src/i18n/da.ts index 59c18e8e92..1bb4758568 100644 --- a/packages/ui/src/i18n/da.ts +++ b/packages/ui/src/i18n/da.ts @@ -39,6 +39,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "prøver igen", "ui.sessionTurn.retry.inSeconds": "om {{seconds}}s", + "ui.sessionTurn.retry.attempt": "forsøg #{{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - forsøg #{{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini er meget overbelastet lige nu", "ui.sessionTurn.error.freeUsageExceeded": "Gratis forbrug overskredet", "ui.sessionTurn.error.addCredits": "Tilføj kreditter", @@ -56,6 +59,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "Overvejer næste skridt", "ui.messagePart.questions.dismissed": "Spørgsmål afvist", + "ui.messagePart.compaction": "Historik komprimeret", "ui.messagePart.context.read.one": "{{count}} læsning", "ui.messagePart.context.read.other": "{{count}} læsninger", "ui.messagePart.context.search.one": "{{count}} søgning", @@ -121,6 +125,7 @@ export const dict = { "ui.message.copyResponse": "Kopier svar", "ui.message.copied": "Kopieret!", "ui.message.interrupted": "Afbrudt", + "ui.message.queued": "I kø", "ui.message.attachment.alt": "vedhæftning", "ui.patch.action.deleted": "Slettet", diff --git a/packages/ui/src/i18n/de.ts b/packages/ui/src/i18n/de.ts index b3fb610615..951833c309 100644 --- a/packages/ui/src/i18n/de.ts +++ b/packages/ui/src/i18n/de.ts @@ -45,6 +45,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "erneuter Versuch", "ui.sessionTurn.retry.inSeconds": "in {{seconds}}s", + "ui.sessionTurn.retry.attempt": "Versuch #{{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - Versuch #{{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini ist gerade sehr überlastet", "ui.sessionTurn.error.freeUsageExceeded": "Kostenloses Nutzungslimit überschritten", "ui.sessionTurn.error.addCredits": "Guthaben aufladen", @@ -62,6 +65,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "Nächste Schritte erwägen", "ui.messagePart.questions.dismissed": "Fragen verworfen", + "ui.messagePart.compaction": "Verlauf komprimiert", "ui.messagePart.context.read.one": "{{count}} Lesevorgang", "ui.messagePart.context.read.other": "{{count}} Lesevorgänge", "ui.messagePart.context.search.one": "{{count}} Suche", @@ -127,6 +131,7 @@ export const dict = { "ui.message.copyResponse": "Antwort kopieren", "ui.message.copied": "Kopiert!", "ui.message.interrupted": "Unterbrochen", + "ui.message.queued": "In Warteschlange", "ui.message.attachment.alt": "Anhang", "ui.patch.action.deleted": "Gelöscht", diff --git a/packages/ui/src/i18n/en.ts b/packages/ui/src/i18n/en.ts index ba4ff62fb4..9c9ae6e27a 100644 --- a/packages/ui/src/i18n/en.ts +++ b/packages/ui/src/i18n/en.ts @@ -41,6 +41,9 @@ export const dict: Record = { "ui.sessionTurn.retry.retrying": "retrying", "ui.sessionTurn.retry.inSeconds": "in {{seconds}}s", + "ui.sessionTurn.retry.attempt": "attempt #{{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - attempt #{{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini is way too hot right now", "ui.sessionTurn.error.freeUsageExceeded": "Free usage exceeded", "ui.sessionTurn.error.addCredits": "Add credits", @@ -63,6 +66,7 @@ export const dict: Record = { "ui.messagePart.option.typeOwnAnswer": "Type your own answer", "ui.messagePart.review.title": "Review your answers", "ui.messagePart.questions.dismissed": "Questions dismissed", + "ui.messagePart.compaction": "History compacted", "ui.messagePart.context.read.one": "{{count}} read", "ui.messagePart.context.read.other": "{{count}} reads", "ui.messagePart.context.search.one": "{{count}} search", @@ -123,6 +127,7 @@ export const dict: Record = { "ui.message.copyResponse": "Copy response", "ui.message.copied": "Copied", "ui.message.interrupted": "Interrupted", + "ui.message.queued": "Queued", "ui.message.attachment.alt": "attachment", "ui.patch.action.deleted": "Deleted", diff --git a/packages/ui/src/i18n/es.ts b/packages/ui/src/i18n/es.ts index 0b4566c9bc..6fb6eea511 100644 --- a/packages/ui/src/i18n/es.ts +++ b/packages/ui/src/i18n/es.ts @@ -40,6 +40,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "reintentando", "ui.sessionTurn.retry.inSeconds": "en {{seconds}}s", + "ui.sessionTurn.retry.attempt": "intento #{{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - intento #{{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini está demasiado saturado", "ui.sessionTurn.error.freeUsageExceeded": "Límite de uso gratuito excedido", "ui.sessionTurn.error.addCredits": "Añadir créditos", @@ -57,6 +60,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "Considerando siguientes pasos", "ui.messagePart.questions.dismissed": "Preguntas descartadas", + "ui.messagePart.compaction": "Historial compactado", "ui.messagePart.context.read.one": "{{count}} lectura", "ui.messagePart.context.read.other": "{{count}} lecturas", "ui.messagePart.context.search.one": "{{count}} búsqueda", @@ -122,6 +126,7 @@ export const dict = { "ui.message.copyResponse": "Copiar respuesta", "ui.message.copied": "¡Copiado!", "ui.message.interrupted": "Interrumpido", + "ui.message.queued": "En cola", "ui.message.attachment.alt": "adjunto", "ui.patch.action.deleted": "Eliminado", diff --git a/packages/ui/src/i18n/fr.ts b/packages/ui/src/i18n/fr.ts index 4092fac9a3..3a77a3f5c6 100644 --- a/packages/ui/src/i18n/fr.ts +++ b/packages/ui/src/i18n/fr.ts @@ -40,6 +40,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "nouvelle tentative", "ui.sessionTurn.retry.inSeconds": "dans {{seconds}}s", + "ui.sessionTurn.retry.attempt": "tentative n°{{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - tentative n°{{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini est en surchauffe", "ui.sessionTurn.error.freeUsageExceeded": "Limite d'utilisation gratuite dépassée", "ui.sessionTurn.error.addCredits": "Ajouter des crédits", @@ -57,6 +60,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "Examen des prochaines étapes", "ui.messagePart.questions.dismissed": "Questions ignorées", + "ui.messagePart.compaction": "Historique compacté", "ui.messagePart.context.read.one": "{{count}} lecture", "ui.messagePart.context.read.other": "{{count}} lectures", "ui.messagePart.context.search.one": "{{count}} recherche", @@ -122,6 +126,7 @@ export const dict = { "ui.message.copyResponse": "Copier la réponse", "ui.message.copied": "Copié !", "ui.message.interrupted": "Interrompu", + "ui.message.queued": "En file", "ui.message.attachment.alt": "pièce jointe", "ui.patch.action.deleted": "Supprimé", diff --git a/packages/ui/src/i18n/ja.ts b/packages/ui/src/i18n/ja.ts index ea855d1b72..9dfb03f76b 100644 --- a/packages/ui/src/i18n/ja.ts +++ b/packages/ui/src/i18n/ja.ts @@ -39,6 +39,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "再試行中", "ui.sessionTurn.retry.inSeconds": "{{seconds}}秒後", + "ui.sessionTurn.retry.attempt": "{{attempt}}回目", + "ui.sessionTurn.retry.attemptLine": "{{line}} - {{attempt}}回目", + "ui.sessionTurn.retry.geminiHot": "gemini が混雑しています", "ui.sessionTurn.error.freeUsageExceeded": "無料使用制限に達しました", "ui.sessionTurn.error.addCredits": "クレジットを追加", @@ -56,6 +59,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "次のステップを検討中", "ui.messagePart.questions.dismissed": "質問をスキップしました", + "ui.messagePart.compaction": "履歴を圧縮しました", "ui.messagePart.context.read.one": "{{count}} 件の読み取り", "ui.messagePart.context.read.other": "{{count}} 件の読み取り", "ui.messagePart.context.search.one": "{{count}} 件の検索", @@ -121,6 +125,7 @@ export const dict = { "ui.message.copyResponse": "応答をコピー", "ui.message.copied": "コピーしました!", "ui.message.interrupted": "中断", + "ui.message.queued": "待機中", "ui.message.attachment.alt": "添付ファイル", "ui.patch.action.deleted": "削除済み", diff --git a/packages/ui/src/i18n/ko.ts b/packages/ui/src/i18n/ko.ts index 80de94e95d..84d261ac89 100644 --- a/packages/ui/src/i18n/ko.ts +++ b/packages/ui/src/i18n/ko.ts @@ -40,6 +40,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "재시도 중", "ui.sessionTurn.retry.inSeconds": "{{seconds}}초 후", + "ui.sessionTurn.retry.attempt": "{{attempt}}번째", + "ui.sessionTurn.retry.attemptLine": "{{line}} - {{attempt}}번째", + "ui.sessionTurn.retry.geminiHot": "gemini가 현재 과부하 상태입니다", "ui.sessionTurn.error.freeUsageExceeded": "무료 사용량 초과", "ui.sessionTurn.error.addCredits": "크레딧 추가", @@ -57,6 +60,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "다음 단계 고려 중", "ui.messagePart.questions.dismissed": "질문 무시됨", + "ui.messagePart.compaction": "기록이 압축됨", "ui.messagePart.context.read.one": "{{count}}개 읽음", "ui.messagePart.context.read.other": "{{count}}개 읽음", "ui.messagePart.context.search.one": "{{count}}개 검색", @@ -122,6 +126,7 @@ export const dict = { "ui.message.copyResponse": "응답 복사", "ui.message.copied": "복사됨!", "ui.message.interrupted": "중단됨", + "ui.message.queued": "대기 중", "ui.message.attachment.alt": "첨부 파일", "ui.patch.action.deleted": "삭제됨", diff --git a/packages/ui/src/i18n/no.ts b/packages/ui/src/i18n/no.ts index 77f6df5545..dd1822beee 100644 --- a/packages/ui/src/i18n/no.ts +++ b/packages/ui/src/i18n/no.ts @@ -43,6 +43,9 @@ export const dict: Record = { "ui.sessionTurn.retry.retrying": "Prøver igjen", "ui.sessionTurn.retry.inSeconds": "om {{seconds}}s", + "ui.sessionTurn.retry.attempt": "forsøk #{{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - forsøk #{{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini er veldig overbelastet nå", "ui.sessionTurn.error.freeUsageExceeded": "Gratis bruk overskredet", "ui.sessionTurn.error.addCredits": "Legg til kreditt", @@ -60,6 +63,7 @@ export const dict: Record = { "ui.sessionTurn.status.consideringNextSteps": "Vurderer neste trinn", "ui.messagePart.questions.dismissed": "Spørsmål avvist", + "ui.messagePart.compaction": "Historikk komprimert", "ui.messagePart.context.read.one": "{{count}} lest", "ui.messagePart.context.read.other": "{{count}} lest", "ui.messagePart.context.search.one": "{{count}} søk", @@ -125,6 +129,7 @@ export const dict: Record = { "ui.message.copyResponse": "Kopier svar", "ui.message.copied": "Kopiert!", "ui.message.interrupted": "Avbrutt", + "ui.message.queued": "I kø", "ui.message.attachment.alt": "vedlegg", "ui.patch.action.deleted": "Slettet", diff --git a/packages/ui/src/i18n/pl.ts b/packages/ui/src/i18n/pl.ts index 877e6505fc..fcfedb2ef9 100644 --- a/packages/ui/src/i18n/pl.ts +++ b/packages/ui/src/i18n/pl.ts @@ -39,6 +39,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "ponawianie", "ui.sessionTurn.retry.inSeconds": "za {{seconds}}s", + "ui.sessionTurn.retry.attempt": "próba #{{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - próba #{{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini jest teraz mocno przeciążony", "ui.sessionTurn.error.freeUsageExceeded": "Przekroczono limit darmowego użytkowania", "ui.sessionTurn.error.addCredits": "Dodaj kredyty", @@ -56,6 +59,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "Rozważanie kolejnych kroków", "ui.messagePart.questions.dismissed": "Pytania odrzucone", + "ui.messagePart.compaction": "Historia skompaktowana", "ui.messagePart.context.read.one": "{{count}} odczyt", "ui.messagePart.context.read.other": "{{count}} odczyty", "ui.messagePart.context.search.one": "{{count}} wyszukiwanie", @@ -121,6 +125,7 @@ export const dict = { "ui.message.copyResponse": "Kopiuj odpowiedź", "ui.message.copied": "Skopiowano!", "ui.message.interrupted": "Przerwano", + "ui.message.queued": "W kolejce", "ui.message.attachment.alt": "załącznik", "ui.patch.action.deleted": "Usunięto", diff --git a/packages/ui/src/i18n/ru.ts b/packages/ui/src/i18n/ru.ts index 545be1b63a..713ff47d1e 100644 --- a/packages/ui/src/i18n/ru.ts +++ b/packages/ui/src/i18n/ru.ts @@ -39,6 +39,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "повтор", "ui.sessionTurn.retry.inSeconds": "через {{seconds}}с", + "ui.sessionTurn.retry.attempt": "попытка №{{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - попытка №{{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini сейчас перегружен", "ui.sessionTurn.error.freeUsageExceeded": "Лимит бесплатного использования превышен", "ui.sessionTurn.error.addCredits": "Добавить кредиты", @@ -56,6 +59,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "Рассмотрение следующих шагов", "ui.messagePart.questions.dismissed": "Вопросы отклонены", + "ui.messagePart.compaction": "История сжата", "ui.messagePart.context.read.one": "{{count}} чтение", "ui.messagePart.context.read.other": "{{count}} чтений", "ui.messagePart.context.search.one": "{{count}} поиск", @@ -121,6 +125,7 @@ export const dict = { "ui.message.copyResponse": "Копировать ответ", "ui.message.copied": "Скопировано!", "ui.message.interrupted": "Прервано", + "ui.message.queued": "В очереди", "ui.message.attachment.alt": "вложение", "ui.patch.action.deleted": "Удалено", diff --git a/packages/ui/src/i18n/th.ts b/packages/ui/src/i18n/th.ts index 54b3db649a..44761a279e 100644 --- a/packages/ui/src/i18n/th.ts +++ b/packages/ui/src/i18n/th.ts @@ -41,6 +41,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "กำลังลองใหม่", "ui.sessionTurn.retry.inSeconds": "ใน {{seconds}}วิ", + "ui.sessionTurn.retry.attempt": "ครั้งที่ {{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - ครั้งที่ {{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini กำลังใช้งานหนาแน่นมาก", "ui.sessionTurn.error.freeUsageExceeded": "เกินขีดจำกัดการใช้งานฟรี", "ui.sessionTurn.error.addCredits": "เพิ่มเครดิต", @@ -58,6 +61,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "พิจารณาขั้นตอนถัดไป", "ui.messagePart.questions.dismissed": "ละทิ้งคำถามแล้ว", + "ui.messagePart.compaction": "ประวัติถูกบีบอัด", "ui.messagePart.context.read.one": "อ่าน {{count}} รายการ", "ui.messagePart.context.read.other": "อ่าน {{count}} รายการ", "ui.messagePart.context.search.one": "ค้นหา {{count}} รายการ", @@ -123,6 +127,7 @@ export const dict = { "ui.message.copyResponse": "คัดลอกคำตอบ", "ui.message.copied": "คัดลอกแล้ว!", "ui.message.interrupted": "ถูกขัดจังหวะ", + "ui.message.queued": "อยู่ในคิว", "ui.message.attachment.alt": "ไฟล์แนบ", "ui.patch.action.deleted": "ลบ", diff --git a/packages/ui/src/i18n/tr.ts b/packages/ui/src/i18n/tr.ts index b68a9b257b..5ec108d4aa 100644 --- a/packages/ui/src/i18n/tr.ts +++ b/packages/ui/src/i18n/tr.ts @@ -36,6 +36,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "yeniden deneniyor", "ui.sessionTurn.retry.inSeconds": "{{seconds}}sn içinde", + "ui.sessionTurn.retry.attempt": "deneme #{{attempt}}", + "ui.sessionTurn.retry.attemptLine": "{{line}} - deneme #{{attempt}}", + "ui.sessionTurn.retry.geminiHot": "gemini şu anda aşırı yoğun", "ui.sessionTurn.error.freeUsageExceeded": "Ücretsiz kullanım aşıldı", "ui.sessionTurn.error.addCredits": "Kredi ekle", @@ -53,6 +56,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "Sonraki adımlar değerlendiriliyor", "ui.messagePart.questions.dismissed": "Sorular reddedildi", + "ui.messagePart.compaction": "Geçmiş sıkıştırıldı", "ui.messagePart.context.read.one": "{{count}} okuma", "ui.messagePart.context.read.other": "{{count}} okuma", "ui.messagePart.context.search.one": "{{count}} arama", @@ -118,6 +122,7 @@ export const dict = { "ui.message.copyResponse": "Yanıtı kopyala", "ui.message.copied": "Kopyalandı", "ui.message.interrupted": "Kesildi", + "ui.message.queued": "Sırada", "ui.message.attachment.alt": "ek", "ui.patch.action.deleted": "Silindi", diff --git a/packages/ui/src/i18n/zh.ts b/packages/ui/src/i18n/zh.ts index 9a00e2dc96..39226605b9 100644 --- a/packages/ui/src/i18n/zh.ts +++ b/packages/ui/src/i18n/zh.ts @@ -44,6 +44,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "重试中", "ui.sessionTurn.retry.inSeconds": "{{seconds}} 秒后", + "ui.sessionTurn.retry.attempt": "第 {{attempt}} 次", + "ui.sessionTurn.retry.attemptLine": "{{line}} - 第 {{attempt}} 次", + "ui.sessionTurn.retry.geminiHot": "gemini 当前过载", "ui.sessionTurn.error.freeUsageExceeded": "免费使用额度已用完", "ui.sessionTurn.error.addCredits": "添加积分", @@ -61,6 +64,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "正在考虑下一步", "ui.messagePart.questions.dismissed": "问题已忽略", + "ui.messagePart.compaction": "历史已压缩", "ui.messagePart.context.read.one": "{{count}} 次读取", "ui.messagePart.context.read.other": "{{count}} 次读取", "ui.messagePart.context.search.one": "{{count}} 次搜索", @@ -126,6 +130,7 @@ export const dict = { "ui.message.copyResponse": "复制回复", "ui.message.copied": "已复制!", "ui.message.interrupted": "已中断", + "ui.message.queued": "排队中", "ui.message.attachment.alt": "附件", "ui.patch.action.deleted": "已删除", diff --git a/packages/ui/src/i18n/zht.ts b/packages/ui/src/i18n/zht.ts index 81a140d933..068e222d65 100644 --- a/packages/ui/src/i18n/zht.ts +++ b/packages/ui/src/i18n/zht.ts @@ -44,6 +44,9 @@ export const dict = { "ui.sessionTurn.retry.retrying": "重試中", "ui.sessionTurn.retry.inSeconds": "{{seconds}} 秒後", + "ui.sessionTurn.retry.attempt": "第 {{attempt}} 次", + "ui.sessionTurn.retry.attemptLine": "{{line}} - 第 {{attempt}} 次", + "ui.sessionTurn.retry.geminiHot": "gemini 目前過載", "ui.sessionTurn.error.freeUsageExceeded": "免費使用額度已用完", "ui.sessionTurn.error.addCredits": "新增點數", @@ -61,6 +64,7 @@ export const dict = { "ui.sessionTurn.status.consideringNextSteps": "正在考慮下一步", "ui.messagePart.questions.dismissed": "問題已略過", + "ui.messagePart.compaction": "歷史已壓縮", "ui.messagePart.context.read.one": "{{count}} 次讀取", "ui.messagePart.context.read.other": "{{count}} 次讀取", "ui.messagePart.context.search.one": "{{count}} 次搜尋", @@ -126,6 +130,7 @@ export const dict = { "ui.message.copyResponse": "複製回覆", "ui.message.copied": "已複製!", "ui.message.interrupted": "已中斷", + "ui.message.queued": "排隊中", "ui.message.attachment.alt": "附件", "ui.patch.action.deleted": "已刪除", diff --git a/packages/ui/src/styles/base.css b/packages/ui/src/styles/base.css index 33a2457058..b5604ad619 100644 --- a/packages/ui/src/styles/base.css +++ b/packages/ui/src/styles/base.css @@ -86,6 +86,17 @@ a { app-region: drag; } +*[data-tauri-drag-region] button, +*[data-tauri-drag-region] a, +*[data-tauri-drag-region] input, +*[data-tauri-drag-region] textarea, +*[data-tauri-drag-region] select, +*[data-tauri-drag-region] [role="button"], +*[data-tauri-drag-region] [role="menuitem"], +*[data-tauri-drag-region] [contenteditable] { + app-region: no-drag; +} + /* Add the correct font weight in Edge and Safari. */ diff --git a/packages/ui/src/styles/index.css b/packages/ui/src/styles/index.css index f822371f70..cec42f5a0c 100644 --- a/packages/ui/src/styles/index.css +++ b/packages/ui/src/styles/index.css @@ -7,6 +7,7 @@ @import "katex/dist/katex.min.css" layer(base); @import "../components/accordion.css" layer(components); +@import "../components/animated-number.css" layer(components); @import "../components/app-icon.css" layer(components); @import "../components/avatar.css" layer(components); @import "../components/basic-tool.css" layer(components); @@ -45,10 +46,16 @@ @import "../components/scroll-view.css" layer(components); @import "../components/session-review.css" layer(components); @import "../components/session-turn.css" layer(components); +@import "../components/shell-submessage.css" layer(components); @import "../components/sticky-accordion-header.css" layer(components); @import "../components/tabs.css" layer(components); @import "../components/tag.css" layer(components); +@import "../components/text-reveal.css" layer(components); +@import "../components/text-strikethrough.css" layer(components); @import "../components/text-shimmer.css" layer(components); +@import "../components/tool-count-label.css" layer(components); +@import "../components/tool-count-summary.css" layer(components); +@import "../components/tool-status-title.css" layer(components); @import "../components/toast.css" layer(components); @import "../components/tooltip.css" layer(components); @import "../components/typewriter.css" layer(components); diff --git a/packages/util/package.json b/packages/util/package.json index 36a235639e..0ca8d23609 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.2.15", + "version": "1.2.16", "private": true, "type": "module", "license": "MIT", diff --git a/packages/web/astro.config.mjs b/packages/web/astro.config.mjs index 612d4fb8cd..110c8ce919 100644 --- a/packages/web/astro.config.mjs +++ b/packages/web/astro.config.mjs @@ -224,7 +224,7 @@ export default defineConfig({ "zh-CN": "使用", "zh-TW": "使用", }, - items: ["tui", "cli", "web", "ide", "zen", "share", "github", "gitlab"], + items: ["go", "tui", "cli", "web", "ide", "zen", "share", "github", "gitlab"], }, { diff --git a/packages/web/package.json b/packages/web/package.json index daf2ad3480..f8f745eec5 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -2,7 +2,7 @@ "name": "@opencode-ai/web", "type": "module", "license": "MIT", - "version": "1.2.15", + "version": "1.2.16", "scripts": { "dev": "astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", diff --git a/packages/web/src/content/docs/ar/config.mdx b/packages/web/src/content/docs/ar/config.mdx index d415969972..5a1c294bf2 100644 --- a/packages/web/src/content/docs/ar/config.mdx +++ b/packages/web/src/content/docs/ar/config.mdx @@ -496,6 +496,7 @@ opencode run "Hello world" - `auto` - ضغط الجلسة تلقائيًا عند امتلاء السياق (الافتراضي: `true`). - `prune` - إزالة مخرجات الأدوات القديمة لتوفير الرموز (tokens) (الافتراضي: `true`). +- `reserved` - مخزن مؤقت للرموز (tokens) من أجل الضغط. يترك نافذة كافية لتجنب الفيضان أثناء الضغط. --- diff --git a/packages/web/src/content/docs/ar/custom-tools.mdx b/packages/web/src/content/docs/ar/custom-tools.mdx index 9382627fab..62eeed9cdc 100644 --- a/packages/web/src/content/docs/ar/custom-tools.mdx +++ b/packages/web/src/content/docs/ar/custom-tools.mdx @@ -79,6 +79,32 @@ export const multiply = tool({ --- +#### تضارب الأسماء مع الأدوات المدمجة + +تُصنّف الأدوات المخصصة حسب اسم الأداة. إذا استخدمت أداة مخصصة نفس اسم أداة مدمجة، فإن الأداة المخصصة تأخذ الأولوية. + +على سبيل المثال، يستبدل هذا الملف أداة `bash` المدمجة: + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +فضّل استخدام أسماء فريدة ما لم تكن تريد استبدال أداة مدمجة عمدا. إذا كنت تريد تعطيل أداة مدمجة ولكن لا تريد استبدالها، استخدم [الأذونات](/docs/permissions). +::: + +--- + ### الوسائط يمكنك استخدام `tool.schema`، وهو في الأساس [Zod](https://zod.dev)، لتعريف أنواع الوسائط. diff --git a/packages/web/src/content/docs/ar/go.mdx b/packages/web/src/content/docs/ar/go.mdx new file mode 100644 index 0000000000..76dbecbd33 --- /dev/null +++ b/packages/web/src/content/docs/ar/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: اشتراك منخفض التكلفة لنماذج البرمجة المفتوحة. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go هو اشتراك منخفض التكلفة بقيمة **10 دولارات شهرياً** يمنحك وصولاً موثوقاً إلى نماذج البرمجة المفتوحة الشائعة. + +:::note +OpenCode Go حالياً في مرحلة تجريبية (beta). +::: + +يعمل Go مثل أي مزود آخر في OpenCode. تشترك في OpenCode Go وتحصل على مفتاح API الخاص بك. إنه **اختياري تماماً** ولا تحتاج إلى استخدامه لاستخدام OpenCode. + +صُمم بشكل أساسي للمستخدمين الدوليين، مع استضافة النماذج في الولايات المتحدة والاتحاد الأوروبي وسنغافورة لضمان وصول عالمي مستقر. + +--- + +## الخلفية (Background) + +أصبحت النماذج المفتوحة جيدة حقاً. فهي تصل الآن إلى أداء قريب من النماذج المملوكة لمهام البرمجة. ولأن العديد من المزودين يمكنهم تقديمها بشكل تنافسي، فهي عادة ما تكون أرخص بكثير. + +ومع ذلك، فإن الحصول على وصول موثوق ومنخفض الكمون (low latency) إليها قد يكون صعباً. يختلف المزودون في الجودة والتوافر. + +:::tip +قمنا باختبار مجموعة مختارة من النماذج والمزودين الذين يعملون بشكل جيد مع OpenCode. +::: + +لإصلاح ذلك، قمنا ببعض الأشياء: + +1. اختبرنا مجموعة مختارة من النماذج المفتوحة وتحدثنا مع فرقهم حول أفضل طريقة لتشغيلها. +2. عملنا بعد ذلك مع عدد قليل من المزودين للتأكد من تقديمها بشكل صحيح. +3. أخيراً، قمنا بقياس أداء (benchmark) مزيج النموذج/المزود وتوصلنا إلى قائمة نشعر بالراحة في التوصية بها. + +يمنحك OpenCode Go الوصول إلى هذه النماذج مقابل **10 دولارات شهرياً**. + +--- + +## كيف يعمل (How it works) + +يعمل OpenCode Go مثل أي مزود آخر في OpenCode. + +1. قم بتسجيل الدخول إلى **OpenCode Zen**، واشترك في Go، وانسخ مفتاح API الخاص بك. +2. قم بتشغيل الأمر `/connect` في واجهة TUI، وحدد `OpenCode Go`، والصق مفتاح API الخاص بك. +3. قم بتشغيل `/models` في واجهة TUI لرؤية قائمة النماذج المتاحة من خلال Go. + +:::note +يمكن لعضو واحد فقط لكل مساحة عمل (workspace) الاشتراك في OpenCode Go. +::: + +تتضمن القائمة الحالية للنماذج: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +قد تتغير قائمة النماذج ونحن نختبر ونضيف نماذج جديدة. + +--- + +## حدود الاستخدام (Usage limits) + +يتضمن OpenCode Go الحدود التالية: + +- **حد 5 ساعات** — 12 دولاراً من الاستخدام +- **حد أسبوعي** — 30 دولاراً من الاستخدام +- **حد شهري** — 60 دولاراً من الاستخدام + +يتم تعريف الحدود بقيمة الدولار. هذا يعني أن عدد طلباتك الفعلي يعتمد على النموذج الذي تستخدمه. تسمح النماذج الأرخص مثل MiniMax M2.5 بمزيد من الطلبات، بينما تسمح النماذج الأعلى تكلفة مثل GLM-5 بعدد أقل. + +يوفر الجدول أدناه عدداً تقديرياً للطلبات بناءً على أنماط استخدام Go النموذجية: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ---------------- | ----- | --------- | ------------ | +| طلبات كل 5 ساعات | 1,150 | 1,850 | 30,000 | +| طلبات أسبوعياً | 2,880 | 4,630 | 75,000 | +| طلبات شهرياً | 5,750 | 9,250 | 150,000 | + +تعتمد التقديرات على أنماط الطلبات المتوسطة الملحوظة: + +- GLM-5 — 700 input, 52,000 cached, 150 output tokens per request +- Kimi K2.5 — 870 input, 55,000 cached, 200 output tokens per request +- MiniMax M2.5 — 300 input, 55,000 cached, 125 output tokens per request + +يمكنك تتبع استخدامك الحالي في **console**. + +:::tip +إذا وصلت إلى حد الاستخدام، يمكنك الاستمرار في استخدام النماذج المجانية. +::: + +قد تتغير حدود الاستخدام ونحن نتعلم من الاستخدام المبكر والملاحظات. + +--- + +### التسعير (Pricing) + +OpenCode Go هي خطة اشتراك بقيمة **10 دولارات شهرياً**. أدناه الأسعار **لكل 1 مليون رمز (token)**. + +| Model | Input | Output | Cached Read | +| ------------ | ----- | ------ | ----------- | +| GLM-5 | $1.00 | $3.20 | $0.20 | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | +| MiniMax M2.5 | $0.30 | $1.20 | $0.03 | + +--- + +### الاستخدام خارج الحدود (Usage beyond limits) + +إذا كان لديك أيضاً أرصدة في رصيد Zen الخاص بك، يمكنك تمكين خيار **Use balance** في الـ console. عند التمكين، سيعود Go لاستخدام رصيد Zen الخاص بك بعد وصولك إلى حدود الاستخدام بدلاً من حظر الطلبات. + +--- + +## نقاط النهاية (Endpoints) + +يمكنك أيضاً الوصول إلى نماذج Go من خلال نقاط نهاية API التالية. + +| Model | Model ID | Endpoint | AI SDK Package | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +يستخدم [model id](/docs/config/#models) في تكوين OpenCode الخاص بك التنسيق `opencode-go/`. على سبيل المثال، بالنسبة لـ Kimi K2.5، ستستخدم `opencode-go/kimi-k2.5` في التكوين الخاص بك. + +--- + +## الخصوصية (Privacy) + +تم تصميم الخطة بشكل أساسي للمستخدمين الدوليين، مع استضافة النماذج في الولايات المتحدة والاتحاد الأوروبي وسنغافورة لضمان وصول عالمي مستقر. + +
تواصل معنا إذا كان لديك أي أسئلة. + +--- + +## الأهداف (Goals) + +أنشأنا OpenCode Go لـ: + +1. جعل برمجة الذكاء الاصطناعي **في المتناول** لمزيد من الناس باشتراك منخفض التكلفة. +2. توفير وصول **موثوق** لأفضل نماذج البرمجة المفتوحة. +3. انتقاء نماذج **مختبرة وتم قياس أدائها** لاستخدام وكيل البرمجة. +4. عدم وجود **قيود (lock-in)** من خلال السماح لك باستخدام أي مزود آخر مع OpenCode أيضاً. diff --git a/packages/web/src/content/docs/ar/lsp.mdx b/packages/web/src/content/docs/ar/lsp.mdx index 541b48ecc9..fd1b455340 100644 --- a/packages/web/src/content/docs/ar/lsp.mdx +++ b/packages/web/src/content/docs/ar/lsp.mdx @@ -182,7 +182,7 @@ description: يتكامل OpenCode مع خوادم LSP لديك. يوفر PHP Intelephense ميزات مدفوعة عبر مفتاح ترخيص. يمكنك تزويده بمفتاح الترخيص عبر وضع (فقط) المفتاح داخل ملف نصي في: -- على macOS/Linux: `$HOME/intelephense/licence.txt` -- على Windows: `%USERPROFILE%/intelephense/licence.txt` +- على macOS/Linux: `$HOME/intelephense/license.txt` +- على Windows: `%USERPROFILE%/intelephense/license.txt` يجب أن يحتوي الملف على مفتاح الترخيص فقط دون أي محتوى إضافي. diff --git a/packages/web/src/content/docs/ar/providers.mdx b/packages/web/src/content/docs/ar/providers.mdx index 1d448986f3..f5dd70125f 100644 --- a/packages/web/src/content/docs/ar/providers.mdx +++ b/packages/web/src/content/docs/ar/providers.mdx @@ -83,6 +83,37 @@ OpenCode Zen هي قائمة نماذج يوفّرها فريق OpenCode وقد --- +## OpenCode Go + +OpenCode Go هي خطة اشتراك منخفضة التكلفة توفّر وصولا موثوقا إلى نماذج البرمجة المفتوحة الشهيرة المقدّمة من فريق OpenCode، والتي تم اختبارها والتحقق من أنها تعمل بشكل جيد مع OpenCode. + +1. شغّل الأمر `/connect` في TUI، واختر `OpenCode Go`، ثم انتقل إلى [opencode.ai/auth](https://opencode.ai/zen). + + ```txt + /connect + ``` + +2. سجّل الدخول، وأضف تفاصيل الفوترة، ثم انسخ مفتاح API الخاص بك. + +3. الصق مفتاح API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل `/models` في TUI لعرض قائمة النماذج التي نوصي بها. + + ```txt + /models + ``` + +يعمل مثل أي مزوّد آخر في OpenCode واستخدامه اختياري بالكامل. + +--- + ## الدليل لنلقِ نظرة على بعض المزوّدات بالتفصيل. إذا رغبت في إضافة مزوّد إلى القائمة، @@ -1476,6 +1507,39 @@ OpenCode Zen هي قائمة من النماذج التي تم اختبارها --- +### STACKIT + +توفّر خدمة STACKIT AI Model Serving بيئة استضافة سيادية مُدارة بالكامل لنماذج الذكاء الاصطناعي، مع التركيز على نماذج LLM مثل Llama وMistral وQwen، مع أقصى درجات سيادة البيانات على بنية تحتية أوروبية. + +1. توجّه إلى [STACKIT Portal](https://portal.stackit.cloud)، وانتقل إلى **AI Model Serving**، وأنشئ رمز مصادقة (auth token) لمشروعك. + + :::tip + تحتاج إلى حساب عميل STACKIT وحساب مستخدم ومشروع قبل إنشاء رموز المصادقة. + ::: + +2. شغّل الأمر `/connect` وابحث عن **STACKIT**. + + ```txt + /connect + ``` + +3. أدخل رمز مصادقة STACKIT AI Model Serving. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. شغّل الأمر `/models` للاختيار من النماذج المتاحة مثل _Qwen3-VL 235B_ أو _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + ### OVHcloud AI Endpoints 1. توجّه إلى [OVHcloud panel](https://ovh.com/manager). انتقل إلى قسم `Public Cloud`، ثم `AI & Machine Learning` > `AI Endpoints`، وفي تبويب `API Keys` انقر **Create a new API key**. diff --git a/packages/web/src/content/docs/ar/sdk.mdx b/packages/web/src/content/docs/ar/sdk.mdx index 83cdcad764..bae101acf0 100644 --- a/packages/web/src/content/docs/ar/sdk.mdx +++ b/packages/web/src/content/docs/ar/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## المخرجات المنظمة + +يمكنك طلب مخرجات JSON منظمة من النموذج عن طريق تحديد `format` مع مخطط JSON. سيستخدم النموذج أداة `StructuredOutput` لإرجاع JSON تم التحقق من صحته ومطابق للمخطط الخاص بك. + +### الاستخدام الأساسي + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Access the structured output +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### أنواع صيغ الإخراج + +| النوع | الوصف | +| ------------- | -------------------------------------------------- | +| `text` | الافتراضي. استجابة نصية قياسية (بدون مخرجات منظمة) | +| `json_schema` | يرجع JSON تم التحقق من صحته ومطابق للمخطط المقدم | + +### صيغة مخطط JSON + +عند استخدام `type: 'json_schema'`، يجب تقديم: + +| الحقل | النوع | الوصف | +| ------------ | --------------- | ------------------------------------------------ | +| `type` | `'json_schema'` | مطلوب. يحدد وضع مخطط JSON | +| `schema` | `object` | مطلوب. كائن مخطط JSON الذي يحدد بنية الإخراج | +| `retryCount` | `number` | اختياري. عدد محاولات إعادة التحقق (الافتراضي: 2) | + +### معالجة الأخطاء + +إذا فشل النموذج في إنتاج مخرجات منظمة صالحة بعد جميع المحاولات، ستتضمن الاستجابة `StructuredOutputError`: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### أفضل الممارسات + +1. **قدّم أوصافا واضحة** في خصائص المخطط لمساعدة النموذج على فهم البيانات التي يجب استخراجها +2. **استخدم `required`** لتحديد الحقول التي يجب أن تكون موجودة +3. **حافظ على تركيز المخططات** - المخططات المتداخلة المعقدة قد تكون أصعب على النموذج لملئها بشكل صحيح +4. **عيّن `retryCount` مناسبا** - قم بزيادته للمخططات المعقدة، وتقليله للمخططات البسيطة + +--- + ## APIs توفر SDK جميع واجهات الخادم عبر عميل آمن للأنواع. @@ -226,27 +298,27 @@ const { providers, default: defaults } = await client.config.providers() ### الجلسات (`session`) -| الطريقة | الوصف | ملاحظات | -| ---------------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | سرد الجلسات | يعيد Session[] | -| `session.get({ path })` | جلب جلسة | يعيد Session | -| `session.children({ path })` | سرد الجلسات الفرعية | يعيد Session[] | -| `session.create({ body })` | إنشاء جلسة | يعيد Session | -| `session.delete({ path })` | حذف جلسة | يعيد `boolean` | -| `session.update({ path, body })` | تحديث خصائص الجلسة | يعيد Session | -| `session.init({ path, body })` | تحليل التطبيق وإنشاء `AGENTS.md` | يعيد `boolean` | -| `session.abort({ path })` | إيقاف جلسة قيد التشغيل | يعيد `boolean` | -| `session.share({ path })` | مشاركة جلسة | يعيد Session | -| `session.unshare({ path })` | إلغاء مشاركة جلسة | يعيد Session | -| `session.summarize({ path, body })` | تلخيص جلسة | يعيد `boolean` | -| `session.messages({ path })` | سرد الرسائل في جلسة | يعيد `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ path })` | جلب تفاصيل الرسالة | يعيد `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | إرسال رسالة مطالبة | `body.noReply: true` يعيد UserMessage (للسياق فقط). الافتراضي يعيد AssistantMessage مع استجابة AI | -| `session.command({ path, body })` | إرسال أمر إلى الجلسة | يعيد `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | تشغيل أمر shell | يعيد AssistantMessage | -| `session.revert({ path, body })` | التراجع عن رسالة | يعيد Session | -| `session.unrevert({ path })` | استعادة الرسائل المتراجع عنها | يعيد Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | الاستجابة لطلب إذن | يعيد `boolean` | +| الطريقة | الوصف | ملاحظات | +| ---------------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `session.list()` | سرد الجلسات | يعيد Session[] | +| `session.get({ path })` | جلب جلسة | يعيد Session | +| `session.children({ path })` | سرد الجلسات الفرعية | يعيد Session[] | +| `session.create({ body })` | إنشاء جلسة | يعيد Session | +| `session.delete({ path })` | حذف جلسة | يعيد `boolean` | +| `session.update({ path, body })` | تحديث خصائص الجلسة | يعيد Session | +| `session.init({ path, body })` | تحليل التطبيق وإنشاء `AGENTS.md` | يعيد `boolean` | +| `session.abort({ path })` | إيقاف جلسة قيد التشغيل | يعيد `boolean` | +| `session.share({ path })` | مشاركة جلسة | يعيد Session | +| `session.unshare({ path })` | إلغاء مشاركة جلسة | يعيد Session | +| `session.summarize({ path, body })` | تلخيص جلسة | يعيد `boolean` | +| `session.messages({ path })` | سرد الرسائل في جلسة | يعيد `{ info: `Message`, parts: `Part[]`}[]` | +| `session.message({ path })` | جلب تفاصيل الرسالة | يعيد `{ info: `Message`, parts: `Part[]`}` | +| `session.prompt({ path, body })` | إرسال رسالة مطالبة | `body.noReply: true` يعيد UserMessage (للسياق فقط). الافتراضي يعيد AssistantMessage مع استجابة AI. يدعم `body.outputFormat` من أجل [المخرجات المنظمة](#المخرجات-المنظمة) | +| `session.command({ path, body })` | إرسال أمر إلى الجلسة | يعيد `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `session.shell({ path, body })` | تشغيل أمر shell | يعيد AssistantMessage | +| `session.revert({ path, body })` | التراجع عن رسالة | يعيد Session | +| `session.unrevert({ path })` | استعادة الرسائل المتراجع عنها | يعيد Session | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | الاستجابة لطلب إذن | يعيد `boolean` | --- diff --git a/packages/web/src/content/docs/ar/tui.mdx b/packages/web/src/content/docs/ar/tui.mdx index 149f290939..bef6fda3fa 100644 --- a/packages/web/src/content/docs/ar/tui.mdx +++ b/packages/web/src/content/docs/ar/tui.mdx @@ -370,6 +370,9 @@ How is auth handled in @packages/functions/src/api/index.ts? - `scroll_acceleration` - فعّل تسارع التمرير على نمط macOS لتمرير سلس وطبيعي. عند تفعيله، تزداد سرعة التمرير مع إيماءات التمرير السريعة وتبقى دقيقة للحركات الأبطأ. **يتقدّم هذا الإعداد على `scroll_speed` ويستبدله عند تفعيله.** - `scroll_speed` - يتحكم في سرعة تمرير واجهة TUI عند استخدام أوامر التمرير (الحد الأدنى: `1`). القيمة الافتراضية هي `3`. **ملاحظة: يتم تجاهل هذا إذا تم ضبط `scroll_acceleration.enabled` على `true`.** +- `diff_style` - يتحكم في عرض الفروقات (diff). القيمة `"auto"` تتكيف مع عرض terminal، و`"stacked"` تعرض عمودًا واحدًا دائمًا. + +استخدم `OPENCODE_TUI_CONFIG` لتحميل مسار إعدادات TUI مخصص. --- diff --git a/packages/web/src/content/docs/ar/zen.mdx b/packages/web/src/content/docs/ar/zen.mdx index f25b321a9b..2810dea7dd 100644 --- a/packages/web/src/content/docs/ar/zen.mdx +++ b/packages/web/src/content/docs/ar/zen.mdx @@ -59,6 +59,7 @@ OpenCode Zen هو بوابة للذكاء الاصطناعي تتيح لك ال | النموذج | معرّف النموذج | نقطة النهاية | حزمة AI SDK | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -68,22 +69,24 @@ OpenCode Zen هو بوابة للذكاء الاصطناعي تتيح لك ال | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -111,29 +114,34 @@ https://opencode.ai/zen/v1/models | النموذج | الإدخال | الإخراج | قراءة مخزنة | كتابة مخزنة | | --------------------------------- | ------- | ------- | ----------- | ----------- | | Big Pickle | Free | Free | Free | - | -| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.5 Free | Free | Free | Free | - | +| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | - | | MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | -| GLM 4.7 Free | Free | Free | Free | - | +| GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 Free | Free | Free | Free | - | | Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - | +| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Claude Sonnet 4.6 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.6 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4.5 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | -| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - | @@ -152,9 +160,7 @@ https://opencode.ai/zen/v1/models النماذج المجانية: -- GLM 4.7 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج. -- Kimi K2.5 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج. -- MiniMax M2.1 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج. +- MiniMax M2.5 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج. - Big Pickle نموذج خفي ومتاح مجانا على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج. تواصل معنا إذا كانت لديك أي أسئلة. @@ -183,9 +189,7 @@ https://opencode.ai/zen/v1/models تتم استضافة جميع نماذجنا في الولايات المتحدة. يلتزم مزوّدونا بسياسة عدم الاحتفاظ بالبيانات (zero-retention) ولا يستخدمون بياناتك لتدريب النماذج، مع الاستثناءات التالية: - Big Pickle: خلال فترة إتاحته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج. -- GLM 4.7 Free: خلال فترة إتاحته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج. -- Kimi K2.5 Free: خلال فترة إتاحته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج. -- MiniMax M2.1 Free: خلال فترة إتاحته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج. +- MiniMax M2.5 Free: خلال فترة إتاحته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج. - OpenAI APIs: يتم الاحتفاظ بالطلبات لمدة 30 يوما وفقا لـ [سياسات بيانات OpenAI](https://platform.openai.com/docs/guides/your-data). - Anthropic APIs: يتم الاحتفاظ بالطلبات لمدة 30 يوما وفقا لـ [سياسات بيانات Anthropic](https://docs.anthropic.com/en/docs/claude-code/data-usage). diff --git a/packages/web/src/content/docs/bs/cli.mdx b/packages/web/src/content/docs/bs/cli.mdx index 049b43497f..7fc594e6c3 100644 --- a/packages/web/src/content/docs/bs/cli.mdx +++ b/packages/web/src/content/docs/bs/cli.mdx @@ -555,6 +555,7 @@ OpenCode se može konfigurirati pomoću varijabli okruženja. | `OPENCODE_AUTO_SHARE` | boolean | Automatski dijeli sesije | | `OPENCODE_GIT_BASH_PATH` | string | Putanja do Git Bash izvršne datoteke na Windows-u | | `OPENCODE_CONFIG` | string | Putanja do konfiguracijskog fajla | +| `OPENCODE_TUI_CONFIG` | string | Putanja do TUI konfiguracijskog fajla | | `OPENCODE_CONFIG_DIR` | string | Putanja do konfiguracijskog direktorija | | `OPENCODE_CONFIG_CONTENT` | string | Inline json konfiguracijski sadržaj | | `OPENCODE_DISABLE_AUTOUPDATE` | boolean | Onemogući automatske provjere ažuriranja | diff --git a/packages/web/src/content/docs/bs/config.mdx b/packages/web/src/content/docs/bs/config.mdx index 3e20f1890d..3183a2f92d 100644 --- a/packages/web/src/content/docs/bs/config.mdx +++ b/packages/web/src/content/docs/bs/config.mdx @@ -14,10 +14,11 @@ OpenCode podržava i **JSON** i **JSONC** (JSON sa komentarima) formate. ```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", - // Theme configuration - "theme": "opencode", "model": "anthropic/claude-sonnet-4-5", "autoupdate": true, + "server": { + "port": 4096, + }, } ``` @@ -30,8 +31,10 @@ Možete postaviti svoju konfiguraciju na nekoliko različitih lokacija i one ima :::note Konfiguracijski fajlovi se **spajaju**, ne zamjenjuju. ::: + Konfiguracijski fajlovi se spajaju, ne zamjenjuju. Kombiniraju se postavke sa sljedećih konfiguracijskih lokacija. Kasnije konfiguracije poništavaju prethodne samo za konfliktne ključeve. Nekonfliktne postavke iz svih konfiguracija su sačuvane. -Na primjer, ako vaša globalna konfiguracija postavlja `theme: "opencode"` i `autoupdate: true`, a vaša projektna konfiguracija postavlja `model: "anthropic/claude-sonnet-4-5"`, konačna konfiguracija će uključivati ​​sve tri postavke. + +Na primjer, ako vaša globalna konfiguracija postavlja `autoupdate: true`, a vaša projektna konfiguracija postavlja `model: "anthropic/claude-sonnet-4-5"`, konačna konfiguracija će uključivati ​​obje postavke. --- @@ -40,23 +43,26 @@ Na primjer, ako vaša globalna konfiguracija postavlja `theme: "opencode"` i `au Izvori konfiguracije se učitavaju ovim redoslijedom (kasniji izvori poništavaju ranije): 1. **Udaljena konfiguracija** (od `.well-known/opencode`) - organizacijske postavke -2. **Globalna konfiguracija** (`~/.config/opencode/opencode.json`) - korisničke postavke +2. **Globalna konfiguracija** (`~/.config/opencode/opencode.json`) - korisničke preferencije 3. **Prilagođena konfiguracija** (`OPENCODE_CONFIG` env var) - prilagođena preinačenja 4. **Konfiguracija projekta** (`opencode.json` u projektu) - postavke specifične za projekat 5. **`.opencode` direktoriji** - agenti, komande, dodaci 6. **Inline konfiguracija** (`OPENCODE_CONFIG_CONTENT` env var) - runtime preinačenja - To znači da konfiguracije projekta mogu nadjačati globalne zadane postavke, a globalne konfiguracije mogu nadjačati postavke udaljene organizacije. - :::note - Direktoriji `.opencode` i `~/.config/opencode` koriste **imena u množini** za poddirektorije: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` i `themes/`. Pojedinačna imena (npr. `agent/`) su također podržana za kompatibilnost unatrag. - ::: +To znači da konfiguracije projekta mogu nadjačati globalne zadane postavke, a globalne konfiguracije mogu nadjačati postavke udaljene organizacije. + +:::note +Direktoriji `.opencode` i `~/.config/opencode` koriste **imena u množini** za poddirektorije: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/` i `themes/`. Pojedinačna imena (npr. `agent/`) su također podržana za kompatibilnost unatrag. +::: --- ### Udaljeno (Remote) Organizacije mogu pružiti zadanu konfiguraciju preko `.well-known/opencode` krajnje tačke. Ovo se automatski preuzima kada se autentifikujete kod provajdera koji to podržava. + Prvo se učitava udaljena konfiguracija koja služi kao osnovni sloj. Svi ostali izvori konfiguracije (globalni, projektni) mogu nadjačati ove zadane postavke. + Na primjer, ako vaša organizacija nudi MCP servere koji su po defaultu onemogućeni: ```json title="Remote config from .well-known/opencode" @@ -89,7 +95,10 @@ Možete omogućiti određene servere u vašoj lokalnoj konfiguraciji: ### Globalno -Postavite svoju globalnu OpenCode konfiguraciju u `~/.config/opencode/opencode.json`. Koristite globalnu konfiguraciju za korisničke preferencije kao što su teme, provajderi ili veze tipki. +Postavite svoju globalnu OpenCode konfiguraciju u `~/.config/opencode/opencode.json`. Koristite globalnu konfiguraciju za korisničke preferencije kao što su provajderi, modeli i dozvole. + +Za postavke specifične za TUI, koristite `~/.config/opencode/tui.json`. + Globalna konfiguracija poništava zadane postavke udaljene organizacije. --- @@ -97,10 +106,15 @@ Globalna konfiguracija poništava zadane postavke udaljene organizacije. ### Projekt Dodajte `opencode.json` u korijen projekta. Konfiguracija projekta ima najveći prioritet među standardnim konfiguracijskim datotekama - ona nadjačava globalne i udaljene konfiguracije. + +Za TUI postavke specifične za projekat, dodajte `tui.json` pored njega. + :::tip Postavite specifičnu konfiguraciju projekta u korijen vašeg projekta. ::: + Kada se OpenCode pokrene, traži konfiguracijsku datoteku u trenutnom direktoriju ili prelazi do najbližeg Git direktorija. + Ovo je također sigurno provjeriti u Git i koristi istu shemu kao globalna. --- @@ -134,33 +148,33 @@ Prilagođeni direktorij se učitava nakon direktorija globalne konfiguracije i ` ## Šema Konfiguracijski fajl ima šemu koja je definirana u [**`opencode.ai/config.json`**](https://opencode.ai/config.json). + +TUI konfiguracija koristi [**`opencode.ai/tui.json`**](https://opencode.ai/tui.json). + Vaš editor bi trebao biti u mogućnosti da validira i autodovršava na osnovu šeme. --- ### TUI -Možete konfigurirati postavke specifične za TUI putem opcije `tui`. +Koristite namjenski `tui.json` (ili `tui.jsonc`) fajl za postavke specifične za TUI. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - }, - "diff_style": "auto" - } + "$schema": "https://opencode.ai/tui.json", + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` -Dostupne opcije: +Koristite `OPENCODE_TUI_CONFIG` da pokažete na prilagođeni TUI konfiguracijski fajl. -- `scroll_acceleration.enabled` - Omogući ubrzanje skrolovanja u macOS stilu. **Ima prednost nad `scroll_speed`.** -- `scroll_speed` - Prilagođeni množitelj brzine pomicanja (podrazumevano: `3`, minimalno: `1`). Zanemareno ako je `scroll_acceleration.enabled` `true`. -- `diff_style` - Kontrola prikaza razlike. `"auto"` se prilagođava širini terminala, `"stacked"` uvijek prikazuje jednu kolonu. - [Saznajte više o korištenju TUI](/docs/tui) ovdje. +Stari `theme`, `keybinds`, i `tui` ključevi u `opencode.json` su zastarjeli i automatski će se migrirati kada je to moguće. + +[Saznajte više o korištenju TUI ovdje](/docs/tui#configure). --- @@ -188,7 +202,8 @@ Dostupne opcije: - `mdns` - Omogući mDNS otkrivanje servisa. Ovo omogućava drugim uređajima na mreži da otkriju vaš OpenCode server. - `mdnsDomain` - Prilagođeno ime domene za mDNS servis. Zadano je `opencode.local`. Korisno za pokretanje više instanci na istoj mreži. - `cors` - Dodatni origini koji omogućavaju CORS kada koristite HTTP server iz klijenta baziranog na pretraživaču. Vrijednosti moraju biti puni origin (shema + host + opcijski port), npr. `https://app.example.com`. - [Saznajte više o serveru](/docs/server) ovdje. + +[Saznajte više o serveru ovdje](/docs/server). --- @@ -206,7 +221,7 @@ Možete upravljati alatima koje LLM može koristiti putem opcije `tools`. } ``` -[Saznajte više o alatima](/docs/tools) ovdje. +[Saznajte više o alatima ovdje](/docs/tools). --- @@ -224,6 +239,7 @@ Možete konfigurirati dobavljače i modele koje želite koristiti u svojoj OpenC ``` Opcija `small_model` konfigurira poseban model za lagane zadatke poput generiranja naslova. Podrazumevano, OpenCode pokušava da koristi jeftiniji model ako je dostupan od vašeg provajdera, inače se vraća na vaš glavni model. + Opcije provajdera mogu uključivati ​​`timeout` i `setCacheKey`: ```json title="opencode.json" @@ -242,7 +258,8 @@ Opcije provajdera mogu uključivati ​​`timeout` i `setCacheKey`: - `timeout` - Vrijeme čekanja zahtjeva u milisekundama (podrazumevano: 300000). Postavite na `false` da onemogućite. - `setCacheKey` - Osigurajte da je ključ keš memorije uvijek postavljen za određenog provajdera. - Također možete konfigurirati [lokalne modele](/docs/models#local). [Saznajte više](/docs/models). + +Također možete konfigurirati [lokalne modele](/docs/models#local). [Saznajte više](/docs/models). --- @@ -272,21 +289,23 @@ Amazon Bedrock podržava konfiguraciju specifičnu za AWS: - `region` - AWS regija za Bedrock (zadano na `AWS_REGION` env var ili `us-east-1`) - `profile` - AWS imenovani profil iz `~/.aws/credentials` (zadano na `AWS_PROFILE` env var) - `endpoint` - URL prilagođene krajnje tačke za VPC krajnje tačke. Ovo je alias za generičku opciju `baseURL` koristeći terminologiju specifičnu za AWS. Ako su oba navedena, `endpoint` ima prednost. - :::note - Tokeni nosioca (`AWS_BEARER_TOKEN_BEDROCK` ili `/connect`) imaju prednost nad autentifikacijom zasnovanom na profilu. Pogledajte [prednost autentifikacije](/docs/providers#authentication-precedence) za detalje. - ::: - [Saznajte više o konfiguraciji Amazon Bedrock](/docs/providers#amazon-bedrock). + +:::note +Tokeni nosioca (`AWS_BEARER_TOKEN_BEDROCK` ili `/connect`) imaju prednost nad autentifikacijom zasnovanom na profilu. Pogledajte [prednost autentifikacije](/docs/providers#authentication-precedence) za detalje. +::: + +[Saznajte više o konfiguraciji Amazon Bedrock](/docs/providers#amazon-bedrock). --- -### Tema +### Teme -Možete konfigurirati temu koju želite koristiti u svojoj OpenCode konfiguraciji putem opcije `theme`. +Postavite vašu UI temu u `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "theme": "" + "$schema": "https://opencode.ai/tui.json", + "theme": "tokyonight" } ``` @@ -332,6 +351,7 @@ Možete postaviti zadanog agenta koristeći opciju `default_agent`. Ovo određuj ``` Zadani agent mora biti primarni agent (ne podagent). Ovo može biti ugrađeni agent kao što je `"build"` ili `"plan"`, ili [prilagođeni agent](/docs/agents) koji ste definirali. Ako navedeni agent ne postoji ili je podagent, OpenCode će se vratiti na `"build"` s upozorenjem. + Ova postavka se primjenjuje na sva sučelja: TUI, CLI (`opencode run`), desktop aplikaciju i GitHub Action. --- @@ -352,7 +372,8 @@ Ovo prihvata: - `"manual"` - Dozvoli ručno dijeljenje putem naredbi (podrazumevano) - `"auto"` - Automatski dijelite nove razgovore - `"disabled"` - Onemogući dijeljenje u potpunosti - Podrazumevano, dijeljenje je postavljeno na ručni način rada gdje trebate eksplicitno dijeliti razgovore pomoću naredbe `/share`. + +Podrazumevano, dijeljenje je postavljeno na ručni način rada gdje trebate eksplicitno dijeliti razgovore pomoću naredbe `/share`. --- @@ -384,11 +405,11 @@ Također možete definirati naredbe koristeći markdown fajlove u `~/.config/ope ### Prečice tipki -Možete prilagoditi svoje veze tipki putem opcije `keybinds`. +Prilagodite prečice tipki u `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": {} } ``` @@ -442,6 +463,7 @@ Možete konfigurirati formatere koda putem opcije `formatter`. ### Dozvole Prema zadanim postavkama, OpenCode **dopušta sve operacije** bez potrebe za eksplicitnim dopuštenjem. Ovo možete promijeniti koristeći opciju `permission`. + Na primjer, da osigurate da alati `edit` i `bash` zahtijevaju odobrenje korisnika: ```json title="opencode.json" @@ -467,13 +489,15 @@ Možete kontrolirati ponašanje sažimanja konteksta putem opcije `compaction`. "$schema": "https://opencode.ai/config.json", "compaction": { "auto": true, - "prune": true + "prune": true, + "reserved": 10000 } } ``` - `auto` - Automatski sažimanje sesije kada je kontekst pun (podrazumevano: `true`). - `prune` - Uklonite stare izlaze alata da sačuvate tokene (podrazumevano: `true`). +- `reserved` - Token buffer za sažimanje. Ostavlja dovoljno prostora da se izbjegne prelijevanje tokom sažimanja --- @@ -512,6 +536,7 @@ Možete konfigurirati MCP servere koje želite koristiti putem opcije `mcp`. ### Dodaci [Plugins](/docs/plugins) proširuju OpenCode sa prilagođenim alatima, kukicama i integracijama. + Postavite datoteke dodataka u `.opencode/plugins/` ili `~/.config/opencode/plugins/`. Također možete učitati dodatke iz npm-a preko opcije `plugin`. ```json title="opencode.json" @@ -554,6 +579,7 @@ Možete onemogućiti dobavljače koji se automatski učitavaju preko opcije `dis :::note `disabled_providers` ima prioritet nad `enabled_providers`. ::: + Opcija `disabled_providers` prihvata niz ID-ova provajdera. Kada je provajder onemogućen: - Neće se učitati čak i ako su varijable okruženja postavljene. @@ -574,9 +600,11 @@ Možete odrediti listu dozvoljenih dobavljača putem opcije `enabled_providers`. ``` Ovo je korisno kada želite da ograničite OpenCode da koristi samo određene provajdere umjesto da ih onemogućavate jednog po jednog. + :::note `disabled_providers` ima prioritet nad `enabled_providers`. ::: + Ako se provajder pojavljuje i u `enabled_providers` i `disabled_providers`, `disabled_providers` ima prioritet za kompatibilnost unatrag. --- @@ -649,7 +677,9 @@ Putanja fajla mogu biti: - U odnosu na direktorij konfiguracijskih datoteka - Ili apsolutne staze koje počinju sa `/` ili `~` - Ovo je korisno za: + +Ovo je korisno za: + - Pohranjivanje osjetljivih podataka poput API ključeva u odvojenim datotekama. - Uključujući velike datoteke instrukcija bez zatrpavanja vaše konfiguracije. - Dijeljenje zajedničkih isječaka konfiguracije u više konfiguracijskih datoteka. diff --git a/packages/web/src/content/docs/bs/custom-tools.mdx b/packages/web/src/content/docs/bs/custom-tools.mdx index e452ce6a56..e933c7cb12 100644 --- a/packages/web/src/content/docs/bs/custom-tools.mdx +++ b/packages/web/src/content/docs/bs/custom-tools.mdx @@ -79,6 +79,32 @@ Ovo stvara dva alata: `math_add` i `math_multiply`. --- +#### Sukob imena s ugrađenim alatima + +Prilagođeni alati su prepoznati po imenu. Ako prilagođeni alat koristi isto ime kao ugrađeni alat, prilagođeni alat ima prednost. + +Na primjer, ova datoteka zamjenjuje ugrađeni `bash` alat: + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +Preferirajte jedinstvena imena osim ako namjerno ne želite zamijeniti ugrađeni alat. Ako želite onemogućiti ugrađeni alat, ali ne i nadjačati ga, koristite [dozvole](/docs/permissions). +::: + +--- + ### Argumenti Možete koristiti `tool.schema`, što je samo [Zod](https://zod.dev), da definirate tipove argumenata. @@ -166,4 +192,4 @@ export default tool({ }) ``` -Ovdje koristimo [`Bun.$`\_](https://bun.com/docs/runtime/shell) uslužni program za pokretanje Python skripte. +Ovdje koristimo [`Bun.$`](https://bun.com/docs/runtime/shell) uslužni program za pokretanje Python skripte. diff --git a/packages/web/src/content/docs/bs/go.mdx b/packages/web/src/content/docs/bs/go.mdx new file mode 100644 index 0000000000..ec7bf25945 --- /dev/null +++ b/packages/web/src/content/docs/bs/go.mdx @@ -0,0 +1,159 @@ +--- +title: Go +description: Povoljna pretplata za otvorene modele kodiranja. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go je povoljna pretplata od **$10/mjesečno** koja vam daje pouzdan pristup popularnim otvorenim modelima kodiranja. + +:::note +OpenCode Go je trenutno u beta fazi. +::: + +Go funkcioniše kao bilo koji drugi pružatelj usluga u OpenCode-u. Pretplatite se na OpenCode Go i +dobijete svoj API ključ. To je **potpuno opcionalno** i ne morate ga koristiti da biste +koristili OpenCode. + +Dizajniran je prvenstveno za međunarodne korisnike, sa modelima hostovanim u SAD-u, EU i Singapuru za stabilan globalni pristup. + +--- + +## Pozadina + +Otvoreni modeli su postali zaista dobri. Sada dostižu performanse bliske +vlasničkim modelima za zadatke kodiranja. A budući da ih mnogi pružatelji usluga mogu posluživati +konkurentno, obično su daleko jeftiniji. + +Međutim, dobivanje pouzdanog pristupa s malim kašnjenjem može biti teško. Pružatelji usluga +variraju u kvaliteti i dostupnosti. + +:::tip +Testirali smo odabranu grupu modela i pružatelja usluga koji dobro rade sa OpenCode-om. +::: + +Da bismo ovo riješili, uradili smo nekoliko stvari: + +1. Testirali smo odabranu grupu otvorenih modela i razgovarali sa njihovim timovima o tome kako ih + najbolje pokrenuti. +2. Zatim smo radili sa nekoliko pružatelja usluga kako bismo bili sigurni da su ispravno + posluživani. +3. Konačno, benchmarkirali smo kombinaciju modela/pružatelja usluga i došli do + liste koju se osjećamo dobro preporučiti. + +OpenCode Go vam daje pristup ovim modelima za **$10/mjesečno**. + +--- + +## Kako to funkcioniše + +OpenCode Go funkcioniše kao bilo koji drugi pružatelj usluga u OpenCode-u. + +1. Prijavite se na **OpenCode Zen**, pretplatite se na Go i + kopirajte svoj API ključ. +2. Pokrenite `/connect` komandu u TUI-ju, odaberite `OpenCode Go` i zalijepite + svoj API ključ. +3. Pokrenite `/models` u TUI-ju da vidite listu modela dostupnih putem Go. + +:::note +Samo jedan član po radnom prostoru se može pretplatiti na OpenCode Go. +::: + +Trenutna lista modela uključuje: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +Lista modela se može mijenjati kako testiramo i dodajemo nove. + +--- + +## Ograničenja korištenja + +OpenCode Go uključuje sljedeća ograničenja: + +- **Limit od 5 sati** — $12 korištenja +- **Sedmični limit** — $30 korištenja +- **Mjesečni limit** — $60 korištenja + +Limiti su definisani u dolarskoj vrijednosti. To znači da vaš stvarni broj zahtjeva zavisi od modela koji koristite. Jeftiniji modeli kao što je MiniMax M2.5 omogućavaju više zahtjeva, dok skuplji modeli kao što je GLM-5 omogućavaju manje. + +Tabela ispod pruža procijenjeni broj zahtjeva na osnovu tipičnih Go obrazaca korištenja: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ------------------ | ----- | --------- | ------------ | +| zahtjeva po 5 sati | 1,150 | 1,850 | 30,000 | +| zahtjeva sedmično | 2,880 | 4,630 | 75,000 | +| zahtjeva mjesečno | 5,750 | 9,250 | 150,000 | + +Procjene su zasnovane na uočenim prosječnim obrascima zahtjeva: + +- GLM-5 — 700 ulaznih, 52,000 keširanih, 150 izlaznih tokena po zahtjevu +- Kimi K2.5 — 870 ulaznih, 55,000 keširanih, 200 izlaznih tokena po zahtjevu +- MiniMax M2.5 — 300 ulaznih, 55,000 keširanih, 125 izlaznih tokena po zahtjevu + +Možete pratiti svoje trenutno korištenje u **konzoli**. + +:::tip +Ako dosegnete limit korištenja, možete nastaviti koristiti besplatne modele. +::: + +Ograničenja korištenja se mogu mijenjati kako učimo iz rane upotrebe i povratnih informacija. + +--- + +### Cijene + +OpenCode Go je pretplatnički plan od **$10/mjesečno**. Ispod su cijene **po 1M tokena**. + +| Model | Ulaz | Izlaz | Keširano čitanje | +| ------------ | ----- | ----- | ---------------- | +| GLM-5 | $1.00 | $3.20 | $0.20 | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | +| MiniMax M2.5 | $0.30 | $1.20 | $0.03 | + +--- + +### Korištenje izvan limita + +Ako također imate kredita na svom Zen saldu, možete omogućiti opciju **Use balance** +u konzoli. Kada je omogućeno, Go će se prebaciti na vaš Zen saldo +nakon što dosegnete limite korištenja umjesto blokiranja zahtjeva. + +--- + +## Endpointi + +Također možete pristupiti Go modelima putem sljedećih API endpointa. + +| Model | ID modela | Endpoint | AI SDK Paket | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +[Model id](/docs/config/#models) u vašoj OpenCode konfiguraciji +koristi format `opencode-go/`. Na primjer, za Kimi K2.5, biste +koristili `opencode-go/kimi-k2.5` u vašoj konfiguraciji. + +--- + +## Privatnost + +Plan je dizajniran prvenstveno za međunarodne korisnike, sa modelima hostovanim u SAD-u, EU i Singapuru za stabilan globalni pristup. + +Kontaktirajte nas ako imate bilo kakvih pitanja. + +--- + +## Ciljevi + +Kreirali smo OpenCode Go da: + +1. Učinimo AI kodiranje **pristupačnim** većem broju ljudi uz povoljnu pretplatu. +2. Pružimo **pouzdan** pristup najboljim otvorenim modelima kodiranja. +3. Kurišemo modele koji su **testirani i benchmarkirani** za upotrebu agenata za kodiranje. +4. Nemamo **zaključavanja (lock-in)** omogućavajući vam da koristite bilo kojeg drugog pružatelja usluga sa OpenCode-om također. diff --git a/packages/web/src/content/docs/bs/index.mdx b/packages/web/src/content/docs/bs/index.mdx index 5d21e994f9..4af699485a 100644 --- a/packages/web/src/content/docs/bs/index.mdx +++ b/packages/web/src/content/docs/bs/index.mdx @@ -80,9 +80,10 @@ Također ga možete instalirati pomoću sljedećih naredbi: - **Korištenje Parua na Arch Linuxu** -```bash - paru -S opencode-bin -``` + ```bash + sudo pacman -S opencode # Arch Linux (Stable) + paru -S opencode-bin # Arch Linux (Latest from AUR) + ``` #### Windows diff --git a/packages/web/src/content/docs/bs/keybinds.mdx b/packages/web/src/content/docs/bs/keybinds.mdx index f35dd38525..a7a6d34a0d 100644 --- a/packages/web/src/content/docs/bs/keybinds.mdx +++ b/packages/web/src/content/docs/bs/keybinds.mdx @@ -3,11 +3,11 @@ title: Prečice tipki description: Prilagodite svoje veze tipki. --- -OpenCode ima listu veza tipki koje možete prilagoditi preko OpenCode konfiguracije. +OpenCode ima listu veza tipki koje možete prilagoditi putem `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -108,18 +108,20 @@ OpenCode ima listu veza tipki koje možete prilagoditi preko OpenCode konfigurac ## Leader tipka OpenCode koristi `leader` (vodeću) tipku za većinu povezivanja tipki. Ovo izbjegava sukobe u vašem terminalu. + Prema zadanim postavkama, `ctrl+x` je vodeća tipka i većina radnji zahtijeva da prvo pritisnete vodeću tipku, a zatim i prečicu. Na primjer, da biste započeli novu sesiju, prvo pritisnite `ctrl+x`, a zatim pritisnite `n`. + Ne morate koristiti vodeću tipku za svoje veze tipki, ali preporučujemo da to učinite. --- ## Onemogućavanje prečica tipki -Možete onemogućiti spajanje tipki dodavanjem ključa u svoju konfiguraciju s vrijednošću "none". +Možete onemogućiti spajanje tipki dodavanjem ključa u `tui.json` s vrijednošću "none". -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/bs/lsp.mdx b/packages/web/src/content/docs/bs/lsp.mdx index 463d9a0ad9..8f52f3bf61 100644 --- a/packages/web/src/content/docs/bs/lsp.mdx +++ b/packages/web/src/content/docs/bs/lsp.mdx @@ -8,40 +8,43 @@ OpenCode se integriše sa vašim Language Server Protocol (LSP) serverima kako b ## Ugrađeni OpenCode dolazi sa nekoliko ugrađenih LSP servera za popularne jezike: -| LSP server | Ekstenzije | Zahtjevi -|------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------ | -| astro | .astro | Automatske instalacije za Astro projekte | -| bash | .sh, .bash, .zsh, .ksh | Automatski instalira bash-language-server | -| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Automatske instalacije za C/C++ projekte | -| csharp | .cs | `.NET SDK` instaliran | -| clojure-lsp | .clj, .cljs, .cljc, .edn | `clojure-lsp` komanda dostupna | -| dart | .dart | `dart` komanda dostupna | -| deno | .ts, .tsx, .js, .jsx, .mjs | `deno` komanda dostupna (automatski detektuje deno.json/deno.jsonc) | -| elixir-ls | .ex, .exs | `elixir` komanda dostupna | -| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | `eslint` ovisnost u projektu | -| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` instaliran | -| gleam | .bleam | `gleam` komanda dostupna | -| gopls | .go | `go` komanda dostupna | -| hls | .hs, .lhs | `haskell-language-server-wrapper` komanda dostupna | -| jdtls | .java | `Java SDK (version 21+)` instaliran | -| kotlin-ls | .kt, .kts | Automatske instalacije za Kotlin projekte | -| lua-ls | .lua | Automatske instalacije za Lua projekte | -| nixd | .nix | `nixd` komanda dostupna | -| ocaml-lsp | .ml, .mli | `ocamllsp` komanda dostupna | -| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | `oxlint` zavisnost u projektu | -| php intelephense | .php | Automatske instalacije za PHP projekte | -| prisma | .prisma | `prisma` komanda dostupna | -| pyright | .py, .pyi | `pyright` ovisnost instalirana | -| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | `ruby` i `gem` komande dostupne | -| rust | .rs | `rust-analyzer` komanda dostupna | -| sourcekit-lsp | .swift, .objc, .objcpp | `swift` instaliran (`xcode` na macOS-u) | -| svelte | .svelte | Automatske instalacije za Svelte projekte | -| terraform | .tf, .tfvars | Automatske instalacije iz GitHub izdanja | -| tinymist | .typ, .typc | Automatske instalacije iz GitHub izdanja | -| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` zavisnost u projektu | -| vue | .vue | Automatske instalacije za Vue projekte | -| yaml-ls | .yaml, .yml | Automatski instalira Red Hat yaml-language-server | -| zls | .zig, .zon | `zig` komanda dostupna | + +| LSP server | Ekstenzije | Zahtjevi | +| ------------------ | ------------------------------------------------------------------- | -------------------------------------------------------- | +| astro | .astro | Automatske instalacije za Astro projekte | +| bash | .sh, .bash, .zsh, .ksh | Automatski instalira bash-language-server | +| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Automatske instalacije za C/C++ projekte | +| csharp | .cs | `.NET SDK` instaliran | +| clojure-lsp | .clj, .cljs, .cljc, .edn | `clojure-lsp` komanda dostupna | +| dart | .dart | `dart` komanda dostupna | +| deno | .ts, .tsx, .js, .jsx, .mjs | `deno` komanda dostupna (automatski detektuje deno.json) | +| elixir-ls | .ex, .exs | `elixir` komanda dostupna | +| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | `eslint` ovisnost u projektu | +| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` instaliran | +| gleam | .gleam | `gleam` komanda dostupna | +| gopls | .go | `go` komanda dostupna | +| hls | .hs, .lhs | `haskell-language-server-wrapper` komanda dostupna | +| jdtls | .java | `Java SDK (version 21+)` instaliran | +| julials | .jl | `julia` i `LanguageServer.jl` instalirani | +| kotlin-ls | .kt, .kts | Automatske instalacije za Kotlin projekte | +| lua-ls | .lua | Automatske instalacije za Lua projekte | +| nixd | .nix | `nixd` komanda dostupna | +| ocaml-lsp | .ml, .mli | `ocamllsp` komanda dostupna | +| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | `oxlint` zavisnost u projektu | +| php intelephense | .php | Automatske instalacije za PHP projekte | +| prisma | .prisma | `prisma` komanda dostupna | +| pyright | .py, .pyi | `pyright` ovisnost instalirana | +| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | `ruby` i `gem` komande dostupne | +| rust | .rs | `rust-analyzer` komanda dostupna | +| sourcekit-lsp | .swift, .objc, .objcpp | `swift` instaliran (`xcode` na macOS-u) | +| svelte | .svelte | Automatske instalacije za Svelte projekte | +| terraform | .tf, .tfvars | Automatske instalacije iz GitHub izdanja | +| tinymist | .typ, .typc | Automatske instalacije iz GitHub izdanja | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` zavisnost u projektu | +| vue | .vue | Automatske instalacije za Vue projekte | +| yaml-ls | .yaml, .yml | Automatski instalira Red Hat yaml-language-server | +| zls | .zig, .zon | `zig` komanda dostupna | + LSP serveri su automatski omogućeni kada se otkrije jedna od gore navedenih ekstenzija datoteke i zahtjevi su ispunjeni. :::note Možete onemogućiti automatska preuzimanja LSP servera tako što ćete postaviti varijablu okruženja `OPENCODE_DISABLE_LSP_DOWNLOAD` na `true`. @@ -70,13 +73,15 @@ Možete prilagoditi LSP servere kroz `lsp` odjeljak u vašoj opencode konfigurac ``` Svaki LSP server podržava sljedeće: -| Svojstvo | Vrsta | Opis -|---------------- | -------- | ------------------------------------------------- | -| `disabled` | boolean | Postavite ovo na `true` da onemogućite LSP server | -| `command` | string[] | Naredba za pokretanje LSP servera | -| `extensions` | string[] | Ekstenzije datoteka koje ovaj LSP server treba da rukuje | -| `env` | objekt | Varijable okruženja koje treba postaviti prilikom pokretanja servera | -| `initialization` | objekt | Opcije inicijalizacije za slanje na LSP server | + +| Svojstvo | Vrsta | Opis | +| ---------------- | -------- | -------------------------------------------------------------------- | +| `disabled` | boolean | Postavite ovo na `true` da onemogućite LSP server | +| `command` | string[] | Naredba za pokretanje LSP servera | +| `extensions` | string[] | Ekstenzije datoteka koje ovaj LSP server treba da rukuje | +| `env` | objekt | Varijable okruženja koje treba postaviti prilikom pokretanja servera | +| `initialization` | objekt | Opcije inicijalizacije za slanje na LSP server | + Pogledajmo neke primjere. --- diff --git a/packages/web/src/content/docs/bs/plugins.mdx b/packages/web/src/content/docs/bs/plugins.mdx index 9b7e9f12b7..7e046cb83d 100644 --- a/packages/web/src/content/docs/bs/plugins.mdx +++ b/packages/web/src/content/docs/bs/plugins.mdx @@ -225,7 +225,7 @@ export const NotificationPlugin = async ({ project, client, $, directory, worktr Koristimo `osascript` za pokretanje AppleScript-a na macOS-u. Ovdje ga koristimo za slanje obavještenja. :::note -Ako koristite desktop aplikaciju OpenCode, ona može automatski slati sistemske obavijesti kada je odgovor spreman ili kada dođe do greške u sesiji. +Ako alat dodatka koristi isto ime kao ugrađeni alat, alat dodatka ima prednost. ::: --- diff --git a/packages/web/src/content/docs/bs/providers.mdx b/packages/web/src/content/docs/bs/providers.mdx index 2415cda277..6bdcf45778 100644 --- a/packages/web/src/content/docs/bs/providers.mdx +++ b/packages/web/src/content/docs/bs/providers.mdx @@ -84,6 +84,37 @@ Radi kao i svaki drugi provajder u OpenCode i potpuno je opcionalan za korišten --- +## OpenCode Go + +OpenCode Go je jeftin plan pretplate koji pruža pouzdan pristup popularnim modelima otvorenog kodiranja koje pruža OpenCode tim i koji su testirani i verificirani da dobro rade s OpenCode-om. + +1. Pokrenite naredbu `/connect` u TUI-u, odaberite `OpenCode Go` i idite na [opencode.ai/auth](https://opencode.ai/zen). + + ```txt + /connect + ``` + +2. Prijavite se, dodajte svoje detalje naplate i kopirajte svoj API ključ. + +3. Zalijepite svoj API ključ. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Pokrenite naredbu `/models` u TUI da vidite listu modela koje preporučujemo. + + ```txt + /models + ``` + +Radi kao i svaki drugi provajder u OpenCode i potpuno je opcionalan za korištenje. + +--- + ## Direktorij Pogledajmo neke od provajdera detaljno. Ako želite dodati provajdera na @@ -1479,9 +1510,42 @@ Ove postavke su opcione i treba ih konfigurirati u skladu s vašim SAP AI Core p 5. Pokrenite naredbu `/models` da odaberete između 40+ dostupnih modela. -```txt + ```txt /models -``` + ``` + +--- + +### STACKIT + +STACKIT AI Model Serving pruža potpuno upravljano suvereno hosting okruženje za AI modele, fokusirajući se na LLM-ove kao što su Llama, Mistral i Qwen, uz maksimalan suverenitet podataka na evropskoj infrastrukturi. + +1. Idite na [STACKIT Portal](https://portal.stackit.cloud), idite na **AI Model Serving** i kreirajte token za autentifikaciju za svoj projekat. + + :::tip + Potreban vam je STACKIT korisnički račun, korisnički nalog i projekat prije kreiranja tokena za autentifikaciju. + ::: + +2. Pokrenite naredbu `/connect` i potražite **STACKIT**. + + ```txt + /connect + ``` + +3. Unesite svoj STACKIT AI Model Serving token za autentifikaciju. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Pokrenite naredbu `/models` da odaberete dostupne modele kao što su _Qwen3-VL 235B_ ili _Llama 3.3 70B_. + + ```txt + /models + ``` --- diff --git a/packages/web/src/content/docs/bs/sdk.mdx b/packages/web/src/content/docs/bs/sdk.mdx index fe6ab4ef14..cc9c2b3bf4 100644 --- a/packages/web/src/content/docs/bs/sdk.mdx +++ b/packages/web/src/content/docs/bs/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## Strukturirani izlaz + +Možete zatražiti strukturirani JSON izlaz od modela specificiranjem `format` sa JSON šemom. Model će koristiti `StructuredOutput` alat da vrati validirani JSON koji odgovara vašoj šemi. + +### Osnovna upotreba + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Access the structured output +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### Tipovi formata izlaza + +| Tip | Opis | +| ------------- | ------------------------------------------------------------------- | +| `text` | Default. Standardni tekstualni odgovor (nema strukturiranog izlaza) | +| `json_schema` | Vraća validirani JSON koji odgovara pruženoj šemi | + +### Format JSON šeme + +Kada koristite `type: 'json_schema'`, navedite: + +| Polje | Tip | Opis | +| ------------ | --------------- | ----------------------------------------------------------- | +| `type` | `'json_schema'` | Obavezno. Određuje JSON schema način rada | +| `schema` | `object` | Obavezno. JSON Schema objekt koji definira strukturu izlaza | +| `retryCount` | `number` | Opcionalno. Broj ponovnih pokušaja validacije (default: 2) | + +### Rukovanje greškama + +Ako model ne uspije proizvesti validan strukturirani izlaz nakon svih ponovnih pokušaja, odgovor će uključivati `StructuredOutputError`: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### Najbolje prakse + +1. **Navedite jasne opise** u svojstvima vaše šeme kako biste pomogli modelu da razumije koje podatke treba izdvojiti +2. **Koristite `required`** da odredite koja polja moraju biti prisutna +3. **Držite šeme fokusiranim** - složene ugniježđene šeme modelu mogu biti teže za ispravno popunjavanje +4. **Postavite odgovarajući `retryCount`** - povećajte za složene šeme, smanjite za jednostavne + +--- + ## API-ji SDK izlaže sve server API-je kroz type-safe klijent. @@ -226,27 +298,27 @@ const { providers, default: defaults } = await client.config.providers() ### Sesije -| Metoda | Opis | Napomene | -| ---------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | List sessions | Returns Session[] | -| `session.get({ path })` | Get session | Returns Session | -| `session.children({ path })` | List child sessions | Returns Session[] | -| `session.create({ body })` | Create session | Returns Session | -| `session.delete({ path })` | Delete session | Returns `boolean` | -| `session.update({ path, body })` | Update session properties | Returns Session | -| `session.init({ path, body })` | Analyze app and create `AGENTS.md` | Returns `boolean` | -| `session.abort({ path })` | Abort a running session | Returns `boolean` | -| `session.share({ path })` | Share session | Returns Session | -| `session.unshare({ path })` | Unshare session | Returns Session | -| `session.summarize({ path, body })` | Summarize session | Returns `boolean` | -| `session.messages({ path })` | List messages in a session | Returns `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ path })` | Get message details | Returns `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | Send prompt message | `body.noReply: true` returns UserMessage (context only). Default returns AssistantMessage with AI response | -| `session.command({ path, body })` | Send command to session | Returns `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | Run a shell command | Returns AssistantMessage | -| `session.revert({ path, body })` | Revert a message | Returns Session | -| `session.unrevert({ path })` | Restore reverted messages | Returns Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | Respond to a permission request | Returns `boolean` | +| Metoda | Opis | Napomene | +| ---------------------------------------------------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | List sessions | Returns Session[] | +| `session.get({ path })` | Get session | Returns Session | +| `session.children({ path })` | List child sessions | Returns Session[] | +| `session.create({ body })` | Create session | Returns Session | +| `session.delete({ path })` | Delete session | Returns `boolean` | +| `session.update({ path, body })` | Update session properties | Returns Session | +| `session.init({ path, body })` | Analyze app and create `AGENTS.md` | Returns `boolean` | +| `session.abort({ path })` | Abort a running session | Returns `boolean` | +| `session.share({ path })` | Share session | Returns Session | +| `session.unshare({ path })` | Unshare session | Returns Session | +| `session.summarize({ path, body })` | Summarize session | Returns `boolean` | +| `session.messages({ path })` | List messages in a session | Returns `{ info: `Message`, parts: `Part[]`}[]` | +| `session.message({ path })` | Get message details | Returns `{ info: `Message`, parts: `Part[]`}` | +| `session.prompt({ path, body })` | Send prompt message | `body.noReply: true` returns UserMessage (context only). Default returns AssistantMessage with AI response. Supports `body.outputFormat` for [structured output](#strukturirani-izlaz) | +| `session.command({ path, body })` | Send command to session | Returns `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `session.shell({ path, body })` | Run a shell command | Returns AssistantMessage | +| `session.revert({ path, body })` | Revert a message | Returns Session | +| `session.unrevert({ path })` | Restore reverted messages | Returns Session | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | Respond to a permission request | Returns `boolean` | --- diff --git a/packages/web/src/content/docs/bs/server.mdx b/packages/web/src/content/docs/bs/server.mdx index 7d270fb4aa..5237873d5f 100644 --- a/packages/web/src/content/docs/bs/server.mdx +++ b/packages/web/src/content/docs/bs/server.mdx @@ -86,116 +86,116 @@ opencode server izlaže sljedece API-je. ### Globalno -| Metoda | Putanja | Opis | Odgovor | -| ------ | ---------------- | ------------------------------ | ------------------------------------ | -| `GET` | `/global/health` | Get server health and version | `{ healthy: true, version: string }` | -| `GET` | `/global/event` | Get global events (SSE stream) | Event stream | +| Metoda | Putanja | Opis | Odgovor | +| ------ | ---------------- | ----------------------------------- | ------------------------------------ | +| `GET` | `/global/health` | Dohvati zdravlje i verziju servera | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | Dohvati globalne događaje (SSE tok) | Event stream | --- ### Projekt -| Metoda | Putanja | Opis | Odgovor | -| ------ | ------------------ | ----------------------- | --------------------------------------------- | -| `GET` | `/project` | List all projects | Project[] | -| `GET` | `/project/current` | Get the current project | Project | +| Metoda | Putanja | Opis | Odgovor | +| ------ | ------------------ | ------------------------ | --------------------------------------------- | +| `GET` | `/project` | Izlistaj sve projekte | Project[] | +| `GET` | `/project/current` | Dohvati trenutni projekt | Project | --- ### Putanja i VCS -| Metoda | Putanja | Opis | Odgovor | -| ------ | ------- | ------------------------------------ | ------------------------------------------- | -| `GET` | `/path` | Get the current path | Path | -| `GET` | `/vcs` | Get VCS info for the current project | VcsInfo | +| Metoda | Putanja | Opis | Odgovor | +| ------ | ------- | ------------------------------------------- | ------------------------------------------- | +| `GET` | `/path` | Dohvati trenutnu putanju | Path | +| `GET` | `/vcs` | Dohvati VCS informacije za trenutni projekt | VcsInfo | --- ### Instanca -| Metoda | Putanja | Opis | Odgovor | -| ------ | ------------------- | ---------------------------- | --------- | -| `POST` | `/instance/dispose` | Dispose the current instance | `boolean` | +| Metoda | Putanja | Opis | Odgovor | +| ------ | ------------------- | ----------------------- | --------- | +| `POST` | `/instance/dispose` | Ugasi trenutnu instancu | `boolean` | --- ### Konfiguracija -| Metoda | Putanja | Opis | Odgovor | -| ------- | ------------------- | --------------------------------- | ---------------------------------------------------------------------------------------- | -| `GET` | `/config` | Get config info | Config | -| `PATCH` | `/config` | Update config | Config | -| `GET` | `/config/providers` | List providers and default models | `{ providers: `Provider[]`, default: { [key: string]: string } }` | +| Metoda | Putanja | Opis | Odgovor | +| ------- | ------------------- | ----------------------------------- | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | Dohvati informacije o konfiguraciji | Config | +| `PATCH` | `/config` | Ažuriraj konfiguraciju | Config | +| `GET` | `/config/providers` | Izlistaj provajdere i zadane modele | `{ providers: `Provider[]`, default: { [key: string]: string } }` | --- ### Provajder -| Metoda | Putanja | Opis | Odgovor | -| ------ | -------------------------------- | ------------------------------------ | ----------------------------------------------------------------------------------- | -| `GET` | `/provider` | List all providers | `{ all: `Provider[]`, default: {...}, connected: string[] }` | -| `GET` | `/provider/auth` | Get provider authentication methods | `{ [providerID: string]: `ProviderAuthMethod[]` }` | -| `POST` | `/provider/{id}/oauth/authorize` | Authorize a provider using OAuth | ProviderAuthAuthorization | -| `POST` | `/provider/{id}/oauth/callback` | Handle OAuth callback for a provider | `boolean` | +| Metoda | Putanja | Opis | Odgovor | +| ------ | -------------------------------- | ----------------------------------------- | ----------------------------------------------------------------------------------- | +| `GET` | `/provider` | Izlistaj sve provajdere | `{ all: `Provider[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | Dohvati metode autentifikacije provajdera | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | Autoriziraj provajdera koristeći OAuth | ProviderAuthAuthorization | +| `POST` | `/provider/{id}/oauth/callback` | Obradi OAuth povratni poziv za provajdera | `boolean` | --- ### Sesije -| Metoda | Putanja | Opis | Napomene | -| -------- | ---------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------- | -| `GET` | `/session` | List all sessions | Returns Session[] | -| `POST` | `/session` | Create a new session | body: `{ parentID?, title? }`, returns Session | -| `GET` | `/session/status` | Get session status for all sessions | Returns `{ [sessionID: string]: `SessionStatus` }` | -| `GET` | `/session/:id` | Get session details | Returns Session | -| `DELETE` | `/session/:id` | Delete a session and all its data | Returns `boolean` | -| `PATCH` | `/session/:id` | Update session properties | body: `{ title? }`, returns Session | -| `GET` | `/session/:id/children` | Get a session's child sessions | Returns Session[] | -| `GET` | `/session/:id/todo` | Get the todo list for a session | Returns Todo[] | -| `POST` | `/session/:id/init` | Analyze app and create `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returns `boolean` | -| `POST` | `/session/:id/fork` | Fork an existing session at a message | body: `{ messageID? }`, returns Session | -| `POST` | `/session/:id/abort` | Abort a running session | Returns `boolean` | -| `POST` | `/session/:id/share` | Share a session | Returns Session | -| `DELETE` | `/session/:id/share` | Unshare a session | Returns Session | -| `GET` | `/session/:id/diff` | Get the diff for this session | query: `messageID?`, returns FileDiff[] | -| `POST` | `/session/:id/summarize` | Summarize the session | body: `{ providerID, modelID }`, returns `boolean` | -| `POST` | `/session/:id/revert` | Revert a message | body: `{ messageID, partID? }`, returns `boolean` | -| `POST` | `/session/:id/unrevert` | Restore all reverted messages | Returns `boolean` | -| `POST` | `/session/:id/permissions/:permissionID` | Respond to a permission request | body: `{ response, remember? }`, returns `boolean` | +| Metoda | Putanja | Opis | Napomene | +| -------- | ---------------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------- | +| `GET` | `/session` | Izlistaj sve sesije | Returns Session[] | +| `POST` | `/session` | Kreiraj novu sesiju | body: `{ parentID?, title? }`, returns Session | +| `GET` | `/session/status` | Dohvati status sesije za sve sesije | Returns `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | Dohvati detalje sesije | Returns Session | +| `DELETE` | `/session/:id` | Obriši sesiju i sve njene podatke | Returns `boolean` | +| `PATCH` | `/session/:id` | Ažuriraj svojstva sesije | body: `{ title? }`, returns Session | +| `GET` | `/session/:id/children` | Dohvati pod-sesije sesije | Returns Session[] | +| `GET` | `/session/:id/todo` | Dohvati listu zadataka za sesiju | Returns Todo[] | +| `POST` | `/session/:id/init` | Analiziraj aplikaciju i kreiraj `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returns `boolean` | +| `POST` | `/session/:id/fork` | Granaj postojeću sesiju na poruci | body: `{ messageID? }`, returns Session | +| `POST` | `/session/:id/abort` | Prekini sesiju u toku | Returns `boolean` | +| `POST` | `/session/:id/share` | Podijeli sesiju | Returns Session | +| `DELETE` | `/session/:id/share` | Prestani dijeliti sesiju | Returns Session | +| `GET` | `/session/:id/diff` | Dohvati razlike za ovu sesiju | query: `messageID?`, returns FileDiff[] | +| `POST` | `/session/:id/summarize` | Rezimiraj sesiju | body: `{ providerID, modelID }`, returns `boolean` | +| `POST` | `/session/:id/revert` | Vrati poruku | body: `{ messageID, partID? }`, returns `boolean` | +| `POST` | `/session/:id/unrevert` | Vrati sve vraćene poruke | Returns `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | Odgovori na zahtjev za dozvolu | body: `{ response, remember? }`, returns `boolean` | --- ### Poruke -| Metoda | Putanja | Opis | Napomene | -| ------ | --------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `GET` | `/session/:id/message` | List messages in a session | query: `limit?`, returns `{ info: `Message`, parts: `Part[]`}[]` | -| `POST` | `/session/:id/message` | Send a message and wait for response | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returns `{ info: `Message`, parts: `Part[]`}` | -| `GET` | `/session/:id/message/:messageID` | Get message details | Returns `{ info: `Message`, parts: `Part[]`}` | -| `POST` | `/session/:id/prompt_async` | Send a message asynchronously (no wait) | body: same as `/session/:id/message`, returns `204 No Content` | -| `POST` | `/session/:id/command` | Execute a slash command | body: `{ messageID?, agent?, model?, command, arguments }`, returns `{ info: `Message`, parts: `Part[]`}` | -| `POST` | `/session/:id/shell` | Run a shell command | body: `{ agent, model?, command }`, returns `{ info: `Message`, parts: `Part[]`}` | +| Metoda | Putanja | Opis | Napomene | +| ------ | --------------------------------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GET` | `/session/:id/message` | Izlistaj poruke u sesiji | query: `limit?`, returns `{ info: `Message`, parts: `Part[]`}[]` | +| `POST` | `/session/:id/message` | Pošalji poruku i čekaj odgovor | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returns `{ info: `Message`, parts: `Part[]`}` | +| `GET` | `/session/:id/message/:messageID` | Dohvati detalje poruke | Returns `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/prompt_async` | Pošalji poruku asinkrono (bez čekanja) | body: same as `/session/:id/message`, returns `204 No Content` | +| `POST` | `/session/:id/command` | Izvrši slash naredbu | body: `{ messageID?, agent?, model?, command, arguments }`, returns `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/shell` | Pokreni shell naredbu | body: `{ agent, model?, command }`, returns `{ info: `Message`, parts: `Part[]`}` | --- ### Naredbe -| Metoda | Putanja | Opis | Odgovor | -| ------ | ---------- | ----------------- | --------------------------------------------- | -| `GET` | `/command` | List all commands | Command[] | +| Metoda | Putanja | Opis | Odgovor | +| ------ | ---------- | -------------------- | --------------------------------------------- | +| `GET` | `/command` | Izlistaj sve naredbe | Command[] | --- ### Datoteke -| Metoda | Putanja | Opis | Odgovor | -| ------ | ------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------- | -| `GET` | `/find?pattern=` | Search for text in files | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | -| `GET` | `/find/file?query=` | Find files and directories by name | `string[]` (paths) | -| `GET` | `/find/symbol?query=` | Find workspace symbols | Symbol[] | -| `GET` | `/file?path=` | List files and directories | FileNode[] | -| `GET` | `/file/content?path=

` | Read a file | FileContent | -| `GET` | `/file/status` | Get status for tracked files | File[] | +| Metoda | Putanja | Opis | Odgovor | +| ------ | ------------------------ | --------------------------------------- | ------------------------------------------------------------------------------------------- | +| `GET` | `/find?pattern=` | Traži tekst u datotekama | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `GET` | `/find/file?query=` | Pronađi datoteke i direktorije po imenu | `string[]` (paths) | +| `GET` | `/find/symbol?query=` | Pronađi simbole radnog prostora | Symbol[] | +| `GET` | `/file?path=` | Izlistaj datoteke i direktorije | FileNode[] | +| `GET` | `/file/content?path=

` | Pročitaj datoteku | FileContent | +| `GET` | `/file/status` | Dohvati status za praćene datoteke | File[] | #### `/find/file` parametri upita @@ -209,10 +209,10 @@ opencode server izlaže sljedece API-je. ### Alati (Eksperimentalno) -| Metoda | Putanja | Opis | Odgovor | -| ------ | ------------------------------------------- | ---------------------------------------- | -------------------------------------------- | -| `GET` | `/experimental/tool/ids` | List all tool IDs | ToolIDs | -| `GET` | `/experimental/tool?provider=

&model=` | List tools with JSON schemas for a model | ToolList | +| Metoda | Putanja | Opis | Odgovor | +| ------ | ------------------------------------------- | -------------------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | Izlistaj sve ID-ove alata | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | Izlistaj alate sa JSON šemama za model | ToolList | --- @@ -220,65 +220,65 @@ opencode server izlaže sljedece API-je. | Metoda | Putanja | Opis | Odgovor | | ------ | ------------ | -------------------------- | -------------------------------------------------------- | -| `GET` | `/lsp` | Get LSP server status | LSPStatus[] | -| `GET` | `/formatter` | Get formatter status | FormatterStatus[] | -| `GET` | `/mcp` | Get MCP server status | `{ [name: string]: `MCPStatus` }` | -| `POST` | `/mcp` | Add MCP server dynamically | body: `{ name, config }`, returns MCP status object | +| `GET` | `/lsp` | Dohvati status LSP servera | LSPStatus[] | +| `GET` | `/formatter` | Dohvati status formatera | FormatterStatus[] | +| `GET` | `/mcp` | Dohvati status MCP servera | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | Dodaj MCP server dinamički | body: `{ name, config }`, returns MCP status object | --- ### Agenti -| Metoda | Putanja | Opis | Odgovor | -| ------ | -------- | ------------------------- | ------------------------------------------- | -| `GET` | `/agent` | List all available agents | Agent[] | +| Metoda | Putanja | Opis | Odgovor | +| ------ | -------- | ---------------------------- | ------------------------------------------- | +| `GET` | `/agent` | Izlistaj sve dostupne agente | Agent[] | --- ### Bilježenje -| Metoda | Putanja | Opis | Odgovor | -| ------ | ------- | ------------------------------------------------------------ | --------- | -| `POST` | `/log` | Write log entry. Body: `{ service, level, message, extra? }` | `boolean` | +| Metoda | Putanja | Opis | Odgovor | +| ------ | ------- | ------------------------------------------------------------------- | --------- | +| `POST` | `/log` | Upiši zapis dnevnika. Tijelo: `{ service, level, message, extra? }` | `boolean` | --- ### TUI -| Metoda | Putanja | Opis | Odgovor | -| ------ | ----------------------- | ------------------------------------------- | ---------------------- | -| `POST` | `/tui/append-prompt` | Append text to the prompt | `boolean` | -| `POST` | `/tui/open-help` | Open the help dialog | `boolean` | -| `POST` | `/tui/open-sessions` | Open the session selector | `boolean` | -| `POST` | `/tui/open-themes` | Open the theme selector | `boolean` | -| `POST` | `/tui/open-models` | Open the model selector | `boolean` | -| `POST` | `/tui/submit-prompt` | Submit the current prompt | `boolean` | -| `POST` | `/tui/clear-prompt` | Clear the prompt | `boolean` | -| `POST` | `/tui/execute-command` | Execute a command (`{ command }`) | `boolean` | -| `POST` | `/tui/show-toast` | Show toast (`{ title?, message, variant }`) | `boolean` | -| `GET` | `/tui/control/next` | Wait for the next control request | Control request object | -| `POST` | `/tui/control/response` | Respond to a control request (`{ body }`) | `boolean` | +| Metoda | Putanja | Opis | Odgovor | +| ------ | ----------------------- | -------------------------------------------------------- | ---------------------- | +| `POST` | `/tui/append-prompt` | Dodaj tekst na prompt | `boolean` | +| `POST` | `/tui/open-help` | Otvori dijalog za pomoć | `boolean` | +| `POST` | `/tui/open-sessions` | Otvori selektor sesija | `boolean` | +| `POST` | `/tui/open-themes` | Otvori selektor tema | `boolean` | +| `POST` | `/tui/open-models` | Otvori selektor modela | `boolean` | +| `POST` | `/tui/submit-prompt` | Pošalji trenutni prompt | `boolean` | +| `POST` | `/tui/clear-prompt` | Očisti prompt | `boolean` | +| `POST` | `/tui/execute-command` | Izvrši naredbu (`{ command }`) | `boolean` | +| `POST` | `/tui/show-toast` | Prikaži toast obavijest (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | Čekaj sljedeći kontrolni zahtjev | Control request object | +| `POST` | `/tui/control/response` | Odgovori na kontrolni zahtjev (`{ body }`) | `boolean` | --- ### Autentifikacija -| Metoda | Putanja | Opis | Odgovor | -| ------ | ----------- | --------------------------------------------------------------- | --------- | -| `PUT` | `/auth/:id` | Set authentication credentials. Body must match provider schema | `boolean` | +| Metoda | Putanja | Opis | Odgovor | +| ------ | ----------- | ------------------------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | Postavi autentifikacijske vjerodajnice. Tijelo mora odgovarati shemi provajdera | `boolean` | --- ### Događaji -| Metoda | Putanja | Opis | Odgovor | -| ------ | -------- | ----------------------------------------------------------------------------- | ------------------------- | -| `GET` | `/event` | Server-sent events stream. First event is `server.connected`, then bus events | Server-sent events stream | +| Metoda | Putanja | Opis | Odgovor | +| ------ | -------- | -------------------------------------------------------------------------------------- | ------------------------- | +| `GET` | `/event` | Tok događaja koje šalje server. Prvi događaj je `server.connected`, zatim bus događaji | Server-sent events stream | --- ### Dokumentacija -| Metoda | Putanja | Opis | Odgovor | -| ------ | ------- | ------------------------- | --------------------------- | -| `GET` | `/doc` | OpenAPI 3.1 specification | HTML page with OpenAPI spec | +| Metoda | Putanja | Opis | Odgovor | +| ------ | ------- | ------------------------- | --------------------------------------- | +| `GET` | `/doc` | OpenAPI 3.1 specifikacija | HTML stranica sa OpenAPI specifikacijom | diff --git a/packages/web/src/content/docs/bs/themes.mdx b/packages/web/src/content/docs/bs/themes.mdx index a513e5a209..edb17e6fa4 100644 --- a/packages/web/src/content/docs/bs/themes.mdx +++ b/packages/web/src/content/docs/bs/themes.mdx @@ -61,11 +61,11 @@ System tema je za korisnike koji: ## Korištenje teme -Temu mozete izabrati preko selektora tema komandom `/theme`. Mozete je navesti i u [configu](/docs/config). +Temu mozete izabrati preko selektora tema komandom `/theme`. Ili je možete navesti u `tui.json`. -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` diff --git a/packages/web/src/content/docs/bs/tui.mdx b/packages/web/src/content/docs/bs/tui.mdx index 96b075aa13..ef09a4caa0 100644 --- a/packages/web/src/content/docs/bs/tui.mdx +++ b/packages/web/src/content/docs/bs/tui.mdx @@ -235,7 +235,7 @@ Podijelite trenutnu sesiju. [Saznajte više](/docs/share). Navedite dostupne teme. ```bash frame="none" -/theme +/themes ``` **Tastatura:** `ctrl+x t` @@ -358,24 +358,34 @@ Nekim uređivačima su potrebni argumenti komandne linije da bi se pokrenuli u n ## Konfiguracija -Možete prilagoditi TUI ponašanje putem vašeg OpenCode konfiguracionog fajla. +Možete prilagoditi TUI ponašanje putem `tui.json` (ili `tui.jsonc`). -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +Ovo je odvojeno od `opencode.json`, koji konfiguriše ponašanje servera/izvršavanja. + ### Opcije -- `scroll_acceleration` - ​​Omogućite ubrzanje pomicanja u macOS stilu za glatko, prirodno pomicanje. Kada je omogućeno, brzina pomicanja se povećava brzim pokretima pomicanja i ostaje precizna za sporije pokrete. **Ova postavka ima prednost nad `scroll_speed` i nadjačava je kada je omogućena.** -- `scroll_speed` - ​​Kontrolira koliko brzo TUI skroluje kada se koriste komande za pomeranje (minimalno: `1`). Podrazumevano je `3`. **Napomena: Ovo se zanemaruje ako je `scroll_acceleration.enabled` postavljeno na `true`.** +- `theme` - Postavlja vašu UI temu. [Saznajte više](/docs/themes). +- `keybinds` - Prilagođava prečice na tastaturi. [Saznajte više](/docs/keybinds). +- `scroll_acceleration.enabled` - ​​Omogućite ubrzanje pomicanja u macOS stilu za glatko, prirodno pomicanje. Kada je omogućeno, brzina pomicanja se povećava brzim pokretima pomicanja i ostaje precizna za sporije pokrete. **Ova postavka ima prednost nad `scroll_speed` i nadjačava je kada je omogućena.** +- `scroll_speed` - ​​Kontrolira koliko brzo TUI skroluje kada se koriste komande za pomeranje (minimum: `0.001`, podržava decimalne vrijednosti). Podrazumevano je `3`. **Napomena: Ovo se zanemaruje ako je `scroll_acceleration.enabled` postavljeno na `true`.** +- `diff_style` - Kontrolira prikazivanje razlike. `"auto"` se prilagođava širini terminala, `"stacked"` uvijek prikazuje raspored u jednoj koloni. + +Koristite `OPENCODE_TUI_CONFIG` da učitate prilagođenu putanju TUI konfiguracije. --- diff --git a/packages/web/src/content/docs/bs/zen.mdx b/packages/web/src/content/docs/bs/zen.mdx index f973337086..ad428884d3 100644 --- a/packages/web/src/content/docs/bs/zen.mdx +++ b/packages/web/src/content/docs/bs/zen.mdx @@ -55,6 +55,7 @@ Nasim modelima mozete pristupiti i preko sljedecih API endpointa. | Model | Model ID | Endpoint | AI SDK Package | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -64,22 +65,24 @@ Nasim modelima mozete pristupiti i preko sljedecih API endpointa. | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -106,29 +109,34 @@ Podrzavamo pay-as-you-go model. Ispod su cijene **po 1M tokena**. | Model | Input | Output | Cached Read | Cached Write | | --------------------------------- | ------ | ------ | ----------- | ------------ | | Big Pickle | Free | Free | Free | - | -| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.5 Free | Free | Free | Free | - | +| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | - | | MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | -| GLM 4.7 Free | Free | Free | Free | - | +| GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 Free | Free | Free | Free | - | | Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - | +| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Claude Sonnet 4.6 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.6 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4.5 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | -| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - | @@ -147,10 +155,8 @@ Naknade kartica se prenose po stvarnom trosku (4.4% + $0.30 po transakciji) i ne Besplatni modeli: -- GLM 4.7 Free je dostupan na OpenCode ograniceno vrijeme. Tim koristi taj period za prikupljanje feedbacka i unapredenje modela. -- Kimi K2.5 Free je dostupan na OpenCode ograniceno vrijeme. Tim koristi taj period za prikupljanje feedbacka i unapredenje modela. -- MiniMax M2.1 Free je dostupan na OpenCode ograniceno vrijeme. Tim koristi taj period za prikupljanje feedbacka i unapredenje modela. -- Big Pickle je stealth model koji je besplatan na OpenCode ograniceno vrijeme. Tim koristi taj period za prikupljanje feedbacka i unapredenje modela. +- MiniMax M2.5 Free je dostupan na OpenCode ograniceno vrijeme. Tim koristi taj period za prikupljanje povratnih informacija i poboljsanje modela. +- Big Pickle je stealth model koji je besplatan na OpenCode ograniceno vrijeme. Tim koristi taj period za prikupljanje povratnih informacija i poboljsanje modela. Ako imate pitanja, kontaktirajte nas. @@ -177,11 +183,9 @@ Na primjer, ako postavite mjesecni limit na $20, Zen nece potrositi vise od $20 Svi nasi modeli su hostovani u SAD-u. Provajderi prate zero-retention politiku i ne koriste vase podatke za treniranje modela, uz sljedece izuzetke: - Big Pickle: Tokom besplatnog perioda, prikupljeni podaci mogu se koristiti za poboljsanje modela. -- GLM 4.7 Free: Tokom besplatnog perioda, prikupljeni podaci mogu se koristiti za poboljsanje modela. -- Kimi K2.5 Free: Tokom besplatnog perioda, prikupljeni podaci mogu se koristiti za poboljsanje modela. -- MiniMax M2.1 Free: Tokom besplatnog perioda, prikupljeni podaci mogu se koristiti za poboljsanje modela. -- OpenAI API-ji: Zahtjevi se cuvaju 30 dana prema [OpenAI Data Policies](https://platform.openai.com/docs/guides/your-data). -- Anthropic API-ji: Zahtjevi se cuvaju 30 dana prema [Anthropic Data Policies](https://docs.anthropic.com/en/docs/claude-code/data-usage). +- MiniMax M2.5 Free: Tokom besplatnog perioda, prikupljeni podaci mogu se koristiti za poboljsanje modela. +- OpenAI API-ji: Zahtjevi se cuvaju 30 dana prema [OpenAI's Data Policies](https://platform.openai.com/docs/guides/your-data). +- Anthropic API-ji: Zahtjevi se cuvaju 30 dana prema [Anthropic's Data Policies](https://docs.anthropic.com/en/docs/claude-code/data-usage). --- diff --git a/packages/web/src/content/docs/da/cli.mdx b/packages/web/src/content/docs/da/cli.mdx index c29559df26..5eece6fd0a 100644 --- a/packages/web/src/content/docs/da/cli.mdx +++ b/packages/web/src/content/docs/da/cli.mdx @@ -558,6 +558,7 @@ OpenCode kan konfigureres ved hjælp af miljøvariabler. | `OPENCODE_AUTO_SHARE` | boolean | Del automatisk session | | `OPENCODE_GIT_BASH_PATH` | string | Sti til Git Bash eksekverbar på Windows | | `OPENCODE_CONFIG` | string | Sti til konfigurationsfil | +| `OPENCODE_TUI_CONFIG` | string | Sti til TUI-konfigurationsfil | | `OPENCODE_CONFIG_DIR` | string | Sti til konfigurationsmappe | | `OPENCODE_CONFIG_CONTENT` | string | Indbygget json-konfigurationsindhold | | `OPENCODE_DISABLE_AUTOUPDATE` | boolean | Deaktiver automatisk opdateringskontrol | @@ -582,7 +583,7 @@ OpenCode kan konfigureres ved hjælp af miljøvariabler. --- -### Flag +### Eksperimentel Disse miljøvariabler muliggør eksperimentelle funktioner, der kan ændres eller fjernes. diff --git a/packages/web/src/content/docs/da/config.mdx b/packages/web/src/content/docs/da/config.mdx index 5b45f8b048..18b462580b 100644 --- a/packages/web/src/content/docs/da/config.mdx +++ b/packages/web/src/content/docs/da/config.mdx @@ -14,10 +14,11 @@ OpenCode understøtter både **JSON** og **JSONC** (JSON med kommentarer) format ```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", - // Theme configuration - "theme": "opencode", "model": "anthropic/claude-sonnet-4-5", "autoupdate": true, + "server": { + "port": 4096, + }, } ``` @@ -34,7 +35,7 @@ Konfigurationsfiler **flettes sammen**, erstattes ikke. Konfigurationsfiler flettes sammen, erstattes ikke. Indstillinger fra følgende konfigurationssteder kombineret. Senere konfigurationer tilsidesætter kun tidligere konfigurationer for modstridende nøgler. Ikke-modstridende indstillinger fra alle konfigurationer bevares. -For eksempel, hvis dine globale konfigurationssæt `theme: "opencode"` og `autoupdate: true`, og dine projektkonfigurationssæt `model: "anthropic/claude-sonnet-4-5"`, vil den endelige konfiguration integrere alle tre indstillinger. +For eksempel, hvis dine globale konfigurationssæt `autoupdate: true`, og dine projektkonfigurationssæt `model: "anthropic/claude-sonnet-4-5"`, vil den endelige konfiguration integrere begge indstillinger. --- @@ -490,13 +491,15 @@ Du kan styre kontekstkomprimeringsadfærd gennem indstillingen `compaction`. "$schema": "https://opencode.ai/config.json", "compaction": { "auto": true, - "prune": true + "prune": true, + "reserved": 10000 } } ``` - `auto` - Komprimer automatisk sessionen, når konteksten er fuld (standard: `true`). - `prune` - Fjern gamle værktøjsudgange for at gemme tokens (standard: `true`). +- `reserved` - Tokenbuffer til komprimering. Efterlader nok vindue til at undgå overløb under komprimering --- @@ -582,8 +585,8 @@ Du kan deaktivere udbydere, der indlæses automatisk gennem `disabled_providers` Indstillingen `disabled_providers` accepterer en række udbyder-id'er. Når en udbyder er deaktiveret: -- Det vil ikke blive indlæst, omgivelserne miljøvariabler er indstillet. -- Den vil ikke blive indlæst, gennem API-nøgler er konfigureret kommandoen `/connect`. +- Den vil ikke blive indlæst, selvom miljøvariabler er indstillet. +- Den vil ikke blive indlæst, selvom API-nøgler er konfigureret via `/connect`-kommandoen. - Udbyderens modeller vises ikke på modelvalgslisten. --- diff --git a/packages/web/src/content/docs/da/custom-tools.mdx b/packages/web/src/content/docs/da/custom-tools.mdx index b0839b649c..75746dcb49 100644 --- a/packages/web/src/content/docs/da/custom-tools.mdx +++ b/packages/web/src/content/docs/da/custom-tools.mdx @@ -79,6 +79,32 @@ Dette skaber værktøjer: `math_add` og `math_multiply`. --- +#### Navnekollisioner med indbyggede værktøjer + +Brugerdefinerede værktøjer er identificeret ved værktøjsnavn. Hvis et brugerdefineret værktøj bruger samme navn som et indbygget værktøj, har det brugerdefinerede værktøj forrang. + +For eksempel erstatter denne fil det indbyggede `bash` værktøj: + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +Foretræk unikke navne, medmindre du bevidst ønsker at erstatte et indbygget værktøj. Hvis du vil deaktivere et indbygget værktøj, men ikke overskrive det, skal du bruge [tilladelser](/docs/permissions). +::: + +--- + ### Argumenter Du kan bruge `tool.schema`, som kun er [Zod](https://zod.dev), til at definere argumenttyper. diff --git a/packages/web/src/content/docs/da/go.mdx b/packages/web/src/content/docs/da/go.mdx new file mode 100644 index 0000000000..4d6ca61acc --- /dev/null +++ b/packages/web/src/content/docs/da/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: Lavprisabonnement for åbne kodningsmodeller. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go er et billigt **$10/måned** abonnement, der giver dig pålidelig adgang til populære åbne kodningsmodeller. + +:::note +OpenCode Go er i øjeblikket i beta. +::: + +Go fungerer ligesom enhver anden udbyder i OpenCode. Du abonnerer på OpenCode Go og får din API-nøgle. Det er **helt valgfrit**, og du behøver ikke at bruge det for at bruge OpenCode. + +Det er primært designet til internationale brugere, med modeller hostet i USA, EU og Singapore for stabil global adgang. + +--- + +## Baggrund + +Åbne modeller er blevet virkelig gode. De når nu en ydeevne tæt på proprietære modeller til kodningsopgaver. Og fordi mange udbydere kan tilbyde dem konkurrencedygtigt, er de normalt langt billigere. + +Det kan dog være svært at få pålidelig adgang med lav latenstid til dem. Udbydere varierer i kvalitet og tilgængelighed. + +:::tip +Vi testede en udvalgt gruppe af modeller og udbydere, der fungerer godt med OpenCode. +::: + +For at løse dette gjorde vi et par ting: + +1. Vi testede en udvalgt gruppe af åbne modeller og talte med deres teams om, hvordan man bedst kører dem. +2. Vi arbejdede derefter sammen med nogle få udbydere for at sikre, at disse blev leveret korrekt. +3. Endelig benchmarkede vi kombinationen af model/udbyder og kom frem til en liste, som vi har det godt med at anbefale. + +OpenCode Go giver dig adgang til disse modeller for **$10/måned**. + +--- + +## Sådan fungerer det + +OpenCode Go fungerer ligesom enhver anden udbyder i OpenCode. + +1. Du logger ind på **OpenCode Zen**, abonnerer på Go, og kopierer din API-nøgle. +2. Du kører kommandoen `/connect` i TUI'en, vælger `OpenCode Go`, og indsætter din API-nøgle. +3. Kør `/models` i TUI'en for at se listen over modeller, der er tilgængelige gennem Go. + +:::note +Kun ét medlem pr. workspace kan abonnere på OpenCode Go. +::: + +Den nuværende liste over modeller inkluderer: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +Listen over modeller kan ændre sig, efterhånden som vi tester og tilføjer nye. + +--- + +## Forbrugsgrænser + +OpenCode Go inkluderer følgende grænser: + +- **5 timers grænse** — $12 forbrug +- **Ugentlig grænse** — $30 forbrug +- **Månedlig grænse** — $60 forbrug + +Grænser er defineret i dollarværdi. Det betyder, at dit faktiske antal forespørgsler afhænger af den model, du bruger. Billigere modeller som MiniMax M2.5 tillader flere forespørgsler, mens dyrere modeller som GLM-5 tillader færre. + +Tabellen nedenfor giver et estimeret antal forespørgsler baseret på typiske Go-brugsmønstre: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ------------------------- | ----- | --------- | ------------ | +| forespørgsler pr. 5 timer | 1.150 | 1.850 | 30.000 | +| forespørgsler pr. uge | 2.880 | 4.630 | 75.000 | +| forespørgsler pr. måned | 5.750 | 9.250 | 150.000 | + +Estimater er baseret på observerede gennemsnitlige forespørgselsmønstre: + +- GLM-5 — 700 input, 52.000 cached, 150 output tokens pr. forespørgsel +- Kimi K2.5 — 870 input, 55.000 cached, 200 output tokens pr. forespørgsel +- MiniMax M2.5 — 300 input, 55.000 cached, 125 output tokens pr. forespørgsel + +Du kan spore dit nuværende forbrug i **konsollen**. + +:::tip +Hvis du når forbrugsgrænsen, kan du fortsætte med at bruge de gratis modeller. +::: + +Forbrugsgrænser kan ændre sig, efterhånden som vi lærer fra tidlig brug og feedback. + +--- + +### Priser + +OpenCode Go er en **$10/måned** abonnementsplan. Nedenfor er priserne **pr. 1M tokens**. + +| Model | Input | Output | Cached Læsning | +| ------------ | ----- | ------ | -------------- | +| GLM-5 | $1,00 | $3,20 | $0,20 | +| Kimi K2.5 | $0,60 | $3,00 | $0,10 | +| MiniMax M2.5 | $0,30 | $1,20 | $0,03 | + +--- + +### Forbrug ud over grænser + +Hvis du også har kreditter på din Zen-saldo, kan du aktivere **Brug saldo**-indstillingen i konsollen. Når den er aktiveret, vil Go falde tilbage på din Zen-saldo, efter du har nået dine forbrugsgrænser, i stedet for at blokere forespørgsler. + +--- + +## Endepunkter + +Du kan også få adgang til Go-modeller gennem følgende API-endepunkter. + +| Model | Model ID | Endpoint | AI SDK Pakke | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +[Model-id'et](/docs/config/#models) i din OpenCode-konfiguration bruger formatet `opencode-go/`. For eksempel, for Kimi K2.5, ville du bruge `opencode-go/kimi-k2.5` i din konfiguration. + +--- + +## Privatliv + +Planen er primært designet til internationale brugere, med modeller hostet i USA, EU og Singapore for stabil global adgang. + +Kontakt os hvis du har spørgsmål. + +--- + +## Mål + +Vi skabte OpenCode Go for at: + +1. Gøre AI-kodning **tilgængelig** for flere mennesker med et billigt abonnement. +2. Tilbyde **pålidelig** adgang til de bedste åbne kodningsmodeller. +3. Udvælge modeller, der er **testet og benchmarked** til brug med kodningsagenter. +4. Have **ingen lock-in** ved at tillade dig også at bruge enhver anden udbyder med OpenCode. diff --git a/packages/web/src/content/docs/da/keybinds.mdx b/packages/web/src/content/docs/da/keybinds.mdx index 2da3ff9426..9c066fcb49 100644 --- a/packages/web/src/content/docs/da/keybinds.mdx +++ b/packages/web/src/content/docs/da/keybinds.mdx @@ -3,11 +3,11 @@ title: Tastebindinger description: Tilpas dine nøglebindinger. --- -OpenCode har en liste over nøglebindinger, som du kan tilpasse gennem OpenCode-konfigurationen. +OpenCode har en liste over nøglebindinger, som du kan tilpasse gennem `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -117,11 +117,11 @@ Du behøver ikke bruge en ledernøgle til dine nøglebindinger, men vi anbefaler ## Deaktiver tastebinding -Du kan deaktivere en nøglebinding ved at tilføje nøglen til din konfiguration med værdien "ingen". +Du kan deaktivere en nøglebinding ved at tilføje nøglen til `tui.json` med værdien "none". -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/da/lsp.mdx b/packages/web/src/content/docs/da/lsp.mdx index b0e0d35372..27d43b192b 100644 --- a/packages/web/src/content/docs/da/lsp.mdx +++ b/packages/web/src/content/docs/da/lsp.mdx @@ -20,13 +20,14 @@ OpenCode leveres med flere indbyggede LSP-servere til populære sprog: | clojure-lsp | .clj,.cljs,.cljc,.edn | `clojure-lsp` kommando tilgængelig | | dart | .dart | `dart` kommando tilgængelig | | deno | .ts,.tsx,.js,.jsx,.mjs | `deno` kommando tilgængelig (auto-detects deno.json/deno.jsonc) | -| eliksir-ls | .ex,.exs | `elixir` kommando tilgængelig | +| elixir-ls | .ex,.exs | `elixir` kommando tilgængelig | | eslint | .ts,.tsx,.js,.jsx,.mjs,.cjs,.mts,.cts,.vue | `eslint` afhængighed i projekt | | fsharp | .fs,.fsi,.fsx,.fsscript | `.NET SDK` installere | | gleam | .gleam | `gleam` kommando tilgængelig | | gopls | .go | `go` kommando tilgængelig | | hls | .hs,.lhs | `haskell-language-server-wrapper` kommando tilgængelig | | jdtls | .java | `Java SDK (version 21+)` installere | +| julials | .jl | `julia` og `LanguageServer.jl` installeret | | kotlin-ls | .kt,.kts | Autoinstallationer til Kotlin-projekter | | lua-ls | .lua | Autoinstallationer til Lua-projekter | | nixd | .nix | `nixd` kommando tilgængelig | @@ -46,7 +47,7 @@ OpenCode leveres med flere indbyggede LSP-servere til populære sprog: | yaml-ls | .yaml,.yml | Autoinstallerer Red Hat yaml-language-server | | zls | .zig,.zon | `zig` kommando tilgængelig | -LSP-servere aktiveres automatisk, når en af ​​ovnstående filtypenavne opdages, og kravene er opfyldt. +LSP-servere aktiveres automatisk, når en af ​​ovenstående filtypenavne opdages, og kravene er opfyldt. :::note Du kan deaktivere automatisk LSP-serverdownloads ved at indstille miljøvariablen `OPENCODE_DISABLE_LSP_DOWNLOAD` til `true`. diff --git a/packages/web/src/content/docs/da/plugins.mdx b/packages/web/src/content/docs/da/plugins.mdx index a8532d599c..908c6e1111 100644 --- a/packages/web/src/content/docs/da/plugins.mdx +++ b/packages/web/src/content/docs/da/plugins.mdx @@ -119,7 +119,7 @@ Plugin-funktionen modtager: - `directory`: Den aktuelle arbejdsmappe. - `worktree`: Git worktree-stien. - `client`: En opencode SDK klient til interaktion med AI. -- `-: Buns [shell API](https://bun.com/docs/runtime/shell) til udførelse af kommandoer. +- `$`: Buns [shell API](https://bun.com/docs/runtime/shell) til udførelse af kommandoer. --- @@ -308,6 +308,10 @@ export const CustomToolsPlugin: Plugin = async (ctx) => { Dine tilpassede værktøjer vil være tilgængelige for opencode sammen med indbyggede værktøjer. +:::note +Hvis et plugin-værktøj bruger samme navn som et indbygget værktøj, har plugin-værktøjet forrang. +::: + --- ### Logning diff --git a/packages/web/src/content/docs/da/providers.mdx b/packages/web/src/content/docs/da/providers.mdx index 829ae46134..c5cfe23fa8 100644 --- a/packages/web/src/content/docs/da/providers.mdx +++ b/packages/web/src/content/docs/da/providers.mdx @@ -81,6 +81,37 @@ Det fungerer som alle andre udbydere i OpenCode og er helt valgfrit at bruge. --- +## OpenCode Go + +OpenCode Go er en billig abonnementsplan, der giver pålidelig adgang til populære åbne kodningsmodeller leveret af OpenCode-teamet, som er testet og verificeret til at fungere godt med OpenCode. + +1. Kør kommandoen `/connect` i TUI, vælg `OpenCode Go`, og gå til [opencode.ai/auth](https://opencode.ai/zen). + + ```txt + /connect + ``` + +2. Log ind, tilføj dine faktureringsoplysninger og kopier din API-nøgle. + +3. Indsæt din API-nøgle. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør `/models` i TUI for at se listen over modeller, vi anbefaler. + + ```txt + /models + ``` + +Det fungerer som alle andre udbydere i OpenCode og er helt valgfrit at bruge. + +--- + ## Katalog Lad os se på nogle af udbyderne i detaljer. Hvis du vil tilføje en udbyder til listen, er du velkommen til at åbne en PR. @@ -1474,6 +1505,39 @@ SAP AI Core giver adgang til 40+ modeller fra OpenAI, Anthropic, Google, Amazon, --- +### STACKIT + +STACKIT AI Model Serving leverer fuldt administreret suverænt hostingmiljø til AI-modeller, med fokus på LLM'er som Llama, Mistral og Qwen, med maksimal datasuverænitet på europæisk infrastruktur. + +1. Gå til [STACKIT Portal](https://portal.stackit.cloud), naviger til **AI Model Serving**, og opret en auth-token til dit projekt. + + :::tip + Du skal have en STACKIT-kundekonto, brugerkonto og projekt, før du opretter auth-tokens. + ::: + +2. Kør kommandoen `/connect` og søg efter **STACKIT**. + + ```txt + /connect + ``` + +3. Indtast din STACKIT AI Model Serving auth-token. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Kør kommandoen `/models` for at vælge fra tilgængelige modeller som _Qwen3-VL 235B_ eller _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + ### OVHcloud AI Endpoints 1. Gå til [OVHcloud-panelet](https://ovh.com/manager). Naviger til `Public Cloud`-delen, `AI & Machine Learning` > `AI Endpoints` og i `API Keys`-fanen klikker du på **Opret en ny API-nøgle**. diff --git a/packages/web/src/content/docs/da/sdk.mdx b/packages/web/src/content/docs/da/sdk.mdx index 3feff27b3b..cde874d5a2 100644 --- a/packages/web/src/content/docs/da/sdk.mdx +++ b/packages/web/src/content/docs/da/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## Struktureret output + +Du kan anmode om struktureret JSON-output fra modellen ved at angive et `format` med et JSON-skema. Modellen vil bruge et `StructuredOutput`-værktøj til at returnere valideret JSON, der matcher dit skema. + +### Grundlæggende brug + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Access the structured output +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### Outputformat-typer + +| Type | Beskrivelse | +| ------------- | -------------------------------------------------------- | +| `text` | Standard. Standard tekstsvar (intet struktureret output) | +| `json_schema` | Returnerer valideret JSON, der matcher det angivne skema | + +### JSON-skemaformat + +Når du bruger `type: 'json_schema'`, skal du angive: + +| Felt | Type | Beskrivelse | +| ------------ | --------------- | ---------------------------------------------------------- | +| `type` | `'json_schema'` | Påkrævet. Angiver JSON-skematilstand | +| `schema` | `object` | Påkrævet. JSON-skemaobjekt, der definerer outputstrukturen | +| `retryCount` | `number` | Valgfri. Antal valideringsforsøg (standard: 2) | + +### Fejlhåndtering + +Hvis modellen ikke formår at producere gyldigt struktureret output efter alle forsøg, vil svaret inkludere en `StructuredOutputError`: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### Bedste praksis + +1. **Giv klare beskrivelser** i dine skemaegenskaber for at hjælpe modellen med at forstå, hvilke data der skal udtrækkes +2. **Brug `required`** til at angive, hvilke felter der skal være til stede +3. **Hold skemaer fokuserede** - komplekse indlejrede skemaer kan være sværere for modellen at udfylde korrekt +4. **Indstil passende `retryCount`** - øg for komplekse skemaer, sænk for enkle + +--- + ## API'er SDK avslører alle server-APIer gjennom en typesikker klient. @@ -226,27 +298,27 @@ const { providers, default: defaults } = await client.config.providers() ### Sessioner -| Metode | Beskrivelse | Noter | -| ---------------------------------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -| `session.list()` | Liste sessioner | Returnerer Session[] | -| `session.get({ path })` | Få session | Returnerer Session | -| `session.children({ path })` | Liste over barnesessioner | Returnerer Session[] | -| `session.create({ body })` | Opret session | Returnerer Session | -| `session.delete({ path })` | Slett session | Returnerer `boolean` | -| `session.update({ path, body })` | Opdater sessionegenskaper | Returnerer Session | -| `session.init({ path, body })` | Analyser appen og lag `AGENTS.md` | Returnerer `boolean` | -| `session.abort({ path })` | Avbryt en løpesession | Returnerer `boolean` | -| `session.share({ path })` | Del sessionen | Returnerer Session | -| `session.unshare({ path })` | Slutt at dele sessionen | Returnerer Session | -| `session.summarize({ path, body })` | Oppsummer sessionen | Returnerer `boolean` | -| `session.messages({ path })` | Liste meldinger i en session | Returnerer `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ path })` | Få meldingsdetaljer | Returnerer `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | Send melding | `body.noReply: true` returnerer UserMessage (kun kontekst). Standard returnerer AssistantMessage med AI svar | -| `session.command({ path, body })` | Send kommando til session | Returnerer `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | Kjør en shell-kommando | Returnerer AssistantMessage | -| `session.revert({ path, body })` | Tilbakestill en melding | Returnerer Session | -| `session.unrevert({ path })` | Gjenopret nulstillete meldinger | Returnerer Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | Svar på en tillatelsesforespørsel | Returnerer `boolean` | +| Metode | Beskrivelse | Noter | +| ---------------------------------------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | Liste sessioner | Returnerer Session[] | +| `session.get({ path })` | Få session | Returnerer Session | +| `session.children({ path })` | Liste over barnesessioner | Returnerer Session[] | +| `session.create({ body })` | Opret session | Returnerer Session | +| `session.delete({ path })` | Slett session | Returnerer `boolean` | +| `session.update({ path, body })` | Opdater sessionegenskaper | Returnerer Session | +| `session.init({ path, body })` | Analyser appen og lag `AGENTS.md` | Returnerer `boolean` | +| `session.abort({ path })` | Avbryt en løpesession | Returnerer `boolean` | +| `session.share({ path })` | Del sessionen | Returnerer Session | +| `session.unshare({ path })` | Slutt at dele sessionen | Returnerer Session | +| `session.summarize({ path, body })` | Oppsummer sessionen | Returnerer `boolean` | +| `session.messages({ path })` | Liste meldinger i en session | Returnerer `{ info: `Message`, parts: `Part[]`}[]` | +| `session.message({ path })` | Få meldingsdetaljer | Returnerer `{ info: `Message`, parts: `Part[]`}` | +| `session.prompt({ path, body })` | Send melding | `body.noReply: true` returnerer UserMessage (kun kontekst). Standard returnerer AssistantMessage med AI svar. Understøtter `body.outputFormat` for [struktureret output](#struktureret-output) | +| `session.command({ path, body })` | Send kommando til session | Returnerer `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `session.shell({ path, body })` | Kjør en shell-kommando | Returnerer AssistantMessage | +| `session.revert({ path, body })` | Tilbakestill en melding | Returnerer Session | +| `session.unrevert({ path })` | Gjenopret nulstillete meldinger | Returnerer Session | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | Svar på en tillatelsesforespørsel | Returnerer `boolean` | --- diff --git a/packages/web/src/content/docs/da/themes.mdx b/packages/web/src/content/docs/da/themes.mdx index 533bef30eb..d250e7f02f 100644 --- a/packages/web/src/content/docs/da/themes.mdx +++ b/packages/web/src/content/docs/da/themes.mdx @@ -61,11 +61,11 @@ Systemtemaet er for brugere som: ## Brug et tema -Du kan velge et tema ved at hente frem temavalg med kommandoen `/theme`. Eller du kan spesifisere det i [config](/docs/config). +Du kan velge et tema ved at hente frem temavalg med kommandoen `/theme`. Eller du kan angive det i `tui.json`. -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` diff --git a/packages/web/src/content/docs/da/tui.mdx b/packages/web/src/content/docs/da/tui.mdx index 21cdbe320e..c1c0de0fd2 100644 --- a/packages/web/src/content/docs/da/tui.mdx +++ b/packages/web/src/content/docs/da/tui.mdx @@ -352,24 +352,34 @@ Nogle editorer kræver kommandolinjeargumenter for at køre i blokeringstilstand ## Konfigurer -Du kan tilpasse TUI-adfærden gennem OpenCode-konfigurationsfilen. +Du kan tilpasse TUI-adfærd gennem `tui.json` (eller `tui.jsonc`). -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +Dette er adskilt fra `opencode.json`, som konfigurerer server-/kørselstidsadfærd. + ### Indstillinger -- `scroll_acceleration` - Aktiver rulleacceleration i macOS-stil for jævn, naturlig rulning. Når aktiveret, øger rullehastigheden med hurtige rullebevægelser og forbliver præcis for langsommere bevægelser. **Denne indstilling har forrang over `scroll_speed` og tilsidesætter den, når den er aktiveret.** -- `scroll_speed` - Styrer hvor hurtigt TUI ruller, når du bruger rullekommandoer (minimum: `1`). Standard er `3`. **Bemærk: Dette ignoreres hvis `scroll_acceleration.enabled` er sat til `true`.** +- `theme` - Indstiller dit brugergrænsefladetema. [Læs mere](/docs/themes). +- `keybinds` - Tilpasser tastaturgenveje. [Læs mere](/docs/keybinds). +- `scroll_acceleration.enabled` - Aktiver rulleacceleration i macOS-stil for jævn, naturlig rulning. Når aktiveret, øger rullehastigheden med hurtige rullebevægelser og forbliver præcis for langsommere bevægelser. **Denne indstilling har forrang over `scroll_speed` og tilsidesætter den, når den er aktiveret.** +- `scroll_speed` - Styrer hvor hurtigt TUI ruller, når du bruger rullekommandoer (minimum: `0.001`, understøtter decimalværdier). Standard er `3`. **Bemærk: Dette ignoreres hvis `scroll_acceleration.enabled` er sat til `true`.** +- `diff_style` - Styrer diff-gengivelse. `"auto"` tilpasser sig terminalbredde, `"stacked"` viser altid et enkeltkolonne-layout. + +Brug `OPENCODE_TUI_CONFIG` til at indlæse en brugerdefineret TUI-konfigurationssti. --- diff --git a/packages/web/src/content/docs/da/zen.mdx b/packages/web/src/content/docs/da/zen.mdx index 128583ad7a..e99c626c57 100644 --- a/packages/web/src/content/docs/da/zen.mdx +++ b/packages/web/src/content/docs/da/zen.mdx @@ -64,6 +64,7 @@ Du kan også få adgang til vores modeller gennem følgende API-endpoints. | Model | Model ID | Endpoint | AI SDK Pakke | | ------------------- | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -73,22 +74,24 @@ Du kan også få adgang til vores modeller gennem følgende API-endpoints. | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | -| Claude Sonnet 4.5 | claude-sonnett-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Sonnet 4 | claude-sonnett-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Gratis | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Gratis | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Gratis | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Gratis | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Tenker | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3-koder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -117,29 +120,34 @@ Vi støtter en pay-as-you-go-model. Nedenfor er priserne **per 1 million tokens* | Model | Input | Output | Cached Læs | Cached Skriv | | --------------------------------- | ------ | ------ | ---------- | ------------ | | Stor sylteagurk | Gratis | Gratis | Gratis | - | -| MiniMax M2.1 Gratis | Gratis | Gratis | Gratis | - | +| MiniMax M2.5 Gratis | Gratis | Gratis | Gratis | - | +| MiniMax M2.5 | $0,30 | $1,20 | $0,06 | - | | MiniMax M2.1 | $0,30 | $1,20 | $0,10 | - | -| GLM 4.7 Gratis | Gratis | Gratis | Gratis | - | +| GLM 5 | $1,00 | $3,20 | $0,20 | - | | GLM 4.7 | $0,60 | $2,20 | $0,10 | - | | GLM 4.6 | $0,60 | $2,20 | $0,10 | - | -| Kimi K2.5 Gratis | Gratis | Gratis | Gratis | - | | Kimi K2.5 | $0,60 | $3,00 | $0,08 | - | | Kimi K2 Tenker | $0,40 | $2,50 | - | - | | Kimi K2 | $0,40 | $2,50 | - | - | | Qwen3-koder 480B | $0,45 | $1,50 | - | - | +| Claude Opus 4.6 (≤ 200K tokens) | $5,00 | $25,00 | $0,50 | $6,25 | +| Claude Opus 4.6 (> 200K tokens) | $10,00 | $37,50 | $1,00 | $12,50 | +| Claude Opus 4.5 | $5,00 | $25,00 | $0,50 | $6,25 | +| Claude Opus 4.1 | $15,00 | $75,00 | $1,50 | $18,75 | +| Claude Sonnet 4.6 (≤ 200K tokens) | $3,00 | $15,00 | $0,30 | $3,75 | +| Claude Sonnet 4.6 (> 200K tokens) | $6,00 | $22,50 | $0,60 | $7,50 | | Claude Sonnet 4.5 (≤ 200K tokens) | $3,00 | $15,00 | $0,30 | $3,75 | | Claude Sonnet 4.5 (> 200K tokens) | $6,00 | $22,50 | $0,60 | $7,50 | | Claude Sonnet 4 (≤ 200K tokens) | $3,00 | $15,00 | $0,30 | $3,75 | | Claude Sonnet 4 (> 200K tokens) | $6,00 | $22,50 | $0,60 | $7,50 | | Claude Haiku 4.5 | $1,00 | $5,00 | $0,10 | $1,25 | | Claude Haiku 3.5 | $0,80 | $4,00 | $0,08 | $1,00 | -| Claude Opus 4.6 (≤ 200K tokens) | $5,00 | $25,00 | $0,50 | $6,25 | -| Claude Opus 4.6 (> 200K tokens) | $10,00 | $37,50 | $1,00 | $12,50 | -| Claude Opus 4.5 | $5,00 | $25,00 | $0,50 | $6,25 | -| Claude Opus 4.1 | $15,00 | $75,00 | $1,50 | $18,75 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2,00 | $12,00 | $0,20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4,00 | $18,00 | $0,40 | - | | Gemini 3 Pro (≤ 200K tokens) | $2,00 | $12,00 | $0,20 | - | | Gemini 3 Pro (> 200K tokens) | $4,00 | $18,00 | $0,40 | - | | Gemini 3 Flash | $0,50 | $3,00 | $0,05 | - | +| GPT 5.3 Codex | $1,75 | $14,00 | $0,175 | - | | GPT 5.2 | $1,75 | $14,00 | $0,175 | - | | GPT 5.2 Codex | $1,75 | $14,00 | $0,175 | - | | GPT 5.1 | $1,07 | $8,50 | $0,107 | - | @@ -158,9 +166,7 @@ Kreditkortgebyrer overføres til kostpris (4,4 % + $0,30 per transaktion); vi op De gratis modeller: -- GLM 4.7 Gratis er tilgængelig på OpenCode i en begrænset periode. Teamet bruger denne tid til at samle feedback og forbedre modellen. -- Kimi K2.5 Gratis er tilgængelig på OpenCode i en begrænset periode. Teamet bruger denne tid til at samle feedback og forbedre modellen. -- MiniMax M2.1 Gratis er tilgængelig på OpenCode i en begrænset periode. Teamet bruger denne tid til at samle feedback og forbedre modellen. +- MiniMax M2.5 Gratis er tilgængelig på OpenCode i en begrænset periode. Teamet bruger denne tid til at samle feedback og forbedre modellen. - Stor sylteagurk er en stealth-model som er gratis på OpenCode i en begrænset periode. Teamet bruger denne tid til at samle feedback og forbedre modellen. Kontakt os hvis du har spørgsmål. @@ -191,9 +197,7 @@ at opkræve dig mere end $20, hvis din saldo går under $5. Alle vores modeller er hostet i USA. Vores udbydere følger en nul-opbevaringspolitik og bruger ikke dine data til modeltræning, med følgende undtagelser: - Stor sylteagurk: I løbet af gratisperioden kan indsamlede data bruges til at forbedre modellen. -- GLM 4.7 Gratis: I løbet af gratisperioden kan indsamlede data bruges til at forbedre modellen. -- Kimi K2.5 Gratis: I løbet af gratisperioden kan indsamlede data bruges til at forbedre modellen. -- MiniMax M2.1 Gratis: I løbet af gratisperioden kan indsamlede data bruges til at forbedre modellen. +- MiniMax M2.5 Gratis: I løbet af gratisperioden kan indsamlede data bruges til at forbedre modellen. - OpenAI API'er: Anmodninger opbevares i 30 dage i overensstemmelse med [OpenAIs datapolitikker](https://platform.openai.com/docs/guides/your-data). - Anthropic API'er: Anmodninger opbevares i 30 dage i overensstemmelse med [Anthropics datapolitikker](https://docs.anthropic.com/en/docs/claude-code/data-usage). diff --git a/packages/web/src/content/docs/de/go.mdx b/packages/web/src/content/docs/de/go.mdx new file mode 100644 index 0000000000..fe4a600cd9 --- /dev/null +++ b/packages/web/src/content/docs/de/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: Kostengünstiges Abonnement für Open-Coding-Modelle. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go ist ein kostengünstiges Abonnement für **10 $/Monat**, das dir zuverlässigen Zugriff auf beliebte Open-Coding-Modelle bietet. + +:::note +OpenCode Go befindet sich derzeit in der Beta-Phase. +::: + +Go funktioniert wie jeder andere Anbieter in OpenCode. Du abonnierst OpenCode Go und erhältst deinen API-Schlüssel. Es ist **völlig optional** und du musst es nicht nutzen, um OpenCode zu verwenden. + +Es wurde primär für internationale Nutzer entwickelt, mit Modellen, die in den USA, der EU und Singapur gehostet werden, um einen stabilen weltweiten Zugriff zu gewährleisten. + +--- + +## Hintergrund + +Offene Modelle sind wirklich gut geworden. Sie erreichen bei Coding-Aufgaben mittlerweile eine Leistung, die der von proprietären Modellen nahekommt. Und da viele Anbieter sie wettbewerbsfähig bereitstellen können, sind sie in der Regel deutlich günstiger. + +Es kann jedoch schwierig sein, einen zuverlässigen Zugang mit niedriger Latenz zu erhalten. Die Anbieter variieren in Qualität und Verfügbarkeit. + +:::tip +Wir haben eine ausgewählte Gruppe von Modellen und Anbietern getestet, die gut mit OpenCode funktionieren. +::: + +Um dies zu lösen, haben wir einige Dinge getan: + +1. Wir haben eine ausgewählte Gruppe offener Modelle getestet und mit deren Teams darüber gesprochen, wie man sie am besten betreibt. +2. Anschließend haben wir mit einigen Anbietern zusammengearbeitet, um sicherzustellen, dass diese korrekt bereitgestellt werden. +3. Schließlich haben wir die Kombination aus Modell und Anbieter einem Benchmark unterzogen und eine Liste erstellt, die wir guten Gewissens empfehlen können. + +OpenCode Go gibt dir Zugriff auf diese Modelle für **10 $/Monat**. + +--- + +## Wie es funktioniert + +OpenCode Go funktioniert wie jeder andere Anbieter in OpenCode. + +1. Du meldest dich bei **OpenCode Zen** an, abonnierst Go und kopierst deinen API-Schlüssel. +2. Du führst den Befehl `/connect` in der TUI aus, wählst `OpenCode Go` und fügst deinen API-Schlüssel ein. +3. Führe `/models` in der TUI aus, um die Liste der über Go verfügbaren Modelle zu sehen. + +:::note +Nur ein Mitglied pro Workspace kann OpenCode Go abonnieren. +::: + +Die aktuelle Liste der Modelle umfasst: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +Die Liste der Modelle kann sich ändern, wenn wir neue testen und hinzufügen. + +--- + +## Nutzungslimits + +OpenCode Go beinhaltet die folgenden Limits: + +- **5-Stunden-Limit** — 12 $ Nutzung +- **Wöchentliches Limit** — 30 $ Nutzung +- **Monatliches Limit** — 60 $ Nutzung + +Die Limits sind in Dollarwerten definiert. Das bedeutet, dass deine tatsächliche Anzahl an Anfragen von dem verwendeten Modell abhängt. Günstigere Modelle wie MiniMax M2.5 ermöglichen mehr Anfragen, während kostenintensivere Modelle wie GLM-5 weniger zulassen. + +Die untenstehende Tabelle bietet eine geschätzte Anzahl an Anfragen basierend auf typischen Go-Nutzungsmustern: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ------------------- | ----- | --------- | ------------ | +| Anfragen pro 5 Std. | 1.150 | 1.850 | 30.000 | +| Anfragen pro Woche | 2.880 | 4.630 | 75.000 | +| Anfragen pro Monat | 5.750 | 9.250 | 150.000 | + +Die Schätzungen basieren auf beobachteten durchschnittlichen Nutzungsmustern: + +- GLM-5 — 700 Input-, 52.000 Cached-, 150 Output-Token pro Anfrage +- Kimi K2.5 — 870 Input-, 55.000 Cached-, 200 Output-Token pro Anfrage +- MiniMax M2.5 — 300 Input-, 55.000 Cached-, 125 Output-Token pro Anfrage + +Du kannst deine aktuelle Nutzung in der **Konsole** verfolgen. + +:::tip +Wenn du das Nutzungslimit erreichst, kannst du weiterhin die kostenlosen Modelle verwenden. +::: + +Nutzungslimits können sich ändern, da wir aus der frühen Nutzung und dem Feedback lernen. + +--- + +### Preise + +OpenCode Go ist ein Abonnementplan für **10 $/Monat**. Unten stehen die Preise **pro 1 Mio. Token**. + +| Modell | Input | Output | Cached Read | +| ------------ | ------ | ------ | ----------- | +| GLM-5 | 1,00 $ | 3,20 $ | 0,20 $ | +| Kimi K2.5 | 0,60 $ | 3,00 $ | 0,10 $ | +| MiniMax M2.5 | 0,30 $ | 1,20 $ | 0,03 $ | + +--- + +### Nutzung über Limits hinaus + +Wenn du auch Guthaben auf deinem Zen-Konto hast, kannst du die Option **Use balance** in der Konsole aktivieren. Wenn aktiviert, greift Go auf dein Zen-Guthaben zurück, nachdem du deine Nutzungslimits erreicht hast, anstatt Anfragen zu blockieren. + +--- + +## Endpunkte + +Du kannst auch über die folgenden API-Endpunkte auf Go-Modelle zugreifen. + +| Modell | Modell-ID | Endpunkt | AI SDK Paket | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +Die [Modell-ID](/docs/config/#models) in deiner OpenCode-Konfiguration verwendet das Format `opencode-go/`. Zum Beispiel würdest du für Kimi K2.5 `opencode-go/kimi-k2.5` in deiner Konfiguration verwenden. + +--- + +## Datenschutz + +Der Plan wurde primär für internationale Nutzer entwickelt, mit Modellen, die in den USA, der EU und Singapur gehostet werden, um einen stabilen weltweiten Zugriff zu gewährleisten. + +Kontaktiere uns, wenn du Fragen hast. + +--- + +## Ziele + +Wir haben OpenCode Go erstellt, um: + +1. AI-Coding für mehr Menschen durch ein kostengünstiges Abonnement **zugänglich** zu machen. +2. **Zuverlässigen** Zugriff auf die besten Open-Coding-Modelle zu bieten. +3. Modelle zu kuratieren, die für den Einsatz von Coding-Agents **getestet und gebenchmarkt** sind. +4. **Keinen Lock-in** zu haben, indem wir dir ermöglichen, jeden anderen Anbieter ebenfalls mit OpenCode zu nutzen. diff --git a/packages/web/src/content/docs/de/providers.mdx b/packages/web/src/content/docs/de/providers.mdx index d72ac5af3d..fa447594d6 100644 --- a/packages/web/src/content/docs/de/providers.mdx +++ b/packages/web/src/content/docs/de/providers.mdx @@ -84,6 +84,37 @@ Es funktioniert wie jeder andere Anbieter in OpenCode und ist völlig optional. --- +## OpenCode Go + +OpenCode Go ist ein kostenguenstiges Abonnement, das zuverlaessigen Zugriff auf beliebte Open-Coding-Modelle bietet, die vom OpenCode-Team getestet und verifiziert wurden, dass sie gut mit OpenCode funktionieren. + +1. Führen Sie den Befehl `/connect` in der TUI aus, waehlen Sie `OpenCode Go` und gehen Sie zu [opencode.ai/auth](https://opencode.ai/zen). + + ```txt + /connect + ``` + +2. Melden Sie sich an, geben Sie Ihre Rechnungsdaten ein und kopieren Sie Ihren API-Schlüssel. + +3. Fügen Sie Ihren API-Schlüssel ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie `/models` in der TUI aus, um die Liste der empfohlenen Modelle zu sehen. + + ```txt + /models + ``` + +Es funktioniert wie jeder andere Anbieter in OpenCode und ist völlig optional. + +--- + ## Verzeichnis Schauen wir uns einige der Anbieter im Detail an. Wenn Sie einen Anbieter hinzufügen möchten @@ -1480,6 +1511,39 @@ SAP AI Core bietet Zugriff auf 40+ Modelle von OpenAI, Anthropic, Google, Amazon --- +### STACKIT + +STACKIT AI Model Serving bietet eine voll verwaltete, souveraene Hosting-Umgebung fuer AI-Modelle, mit Fokus auf LLMs wie Llama, Mistral und Qwen, mit maximaler Datensouveraenitaet auf europaeischer Infrastruktur. + +1. Gehen Sie zum [STACKIT Portal](https://portal.stackit.cloud), navigieren Sie zu **AI Model Serving** und erstellen Sie ein Auth-Token fuer Ihr Projekt. + + :::tip + Sie benoetigen ein STACKIT-Kundenkonto, Benutzerkonto und Projekt, bevor Sie Auth-Tokens erstellen koennen. + ::: + +2. Führen Sie den Befehl `/connect` aus und suchen Sie nach **STACKIT**. + + ```txt + /connect + ``` + +3. Geben Sie Ihr STACKIT AI Model Serving Auth-Token ein. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Führen Sie den Befehl `/models` aus, um aus verfügbaren Modellen wie _Qwen3-VL 235B_ oder _Llama 3.3 70B_ auszuwählen. + + ```txt + /models + ``` + +--- + ### OVHcloud AI Endpoints 1. Gehen Sie zum [OVHcloud panel](https://ovh.com/manager). Navigieren Sie zum Abschnitt `Public Cloud`, `AI & Machine Learning` > `AI Endpoints` und klicken Sie auf der Registerkarte `API Keys` auf **Neuen API-Schlüssel erstellen**. diff --git a/packages/web/src/content/docs/de/sdk.mdx b/packages/web/src/content/docs/de/sdk.mdx index 21791db05d..22e70071d6 100644 --- a/packages/web/src/content/docs/de/sdk.mdx +++ b/packages/web/src/content/docs/de/sdk.mdx @@ -119,6 +119,78 @@ try { --- +## Structured Output + +Du kannst eine strukturierte JSON-Ausgabe vom Modell anfordern, indem du ein `format` mit einem JSON-Schema angibst. Das Modell verwendet dann ein `StructuredOutput`-Tool, um validiertes JSON zurueckzugeben, das deinem Schema entspricht. + +### Grundlegende Verwendung + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Recherchiere Anthropic und gib Firmeninfos zurueck" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Firmenname" }, + founded: { type: "number", description: "Gruendungsjahr" }, + products: { + type: "array", + items: { type: "string" }, + description: "Hauptprodukte", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Zugriff auf die strukturierte Ausgabe +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### Ausgabeformate + +| Type | Description | +| ------------- | ----------------------------------------------------------- | +| `text` | Standard. Normale Textantwort (keine strukturierte Ausgabe) | +| `json_schema` | Gibt validiertes JSON zurueck, das dem Schema entspricht | + +### JSON-Schema-Format + +Bei Verwendung von `type: 'json_schema'` musst du Folgendes angeben: + +| Field | Type | Description | +| ------------ | --------------- | ------------------------------------------------------------- | +| `type` | `'json_schema'` | Erforderlich. Gibt den JSON-Schema-Modus an | +| `schema` | `object` | Erforderlich. JSON-Schema-Objekt, das die Struktur definiert | +| `retryCount` | `number` | Optional. Anzahl der Validierungswiederholungen (Standard: 2) | + +### Fehlerbehandlung + +Wenn das Modell nach allen Wiederholungen keine valide strukturierte Ausgabe liefert, enthaelt die Antwort einen `StructuredOutputError`: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Strukturierte Ausgabe fehlgeschlagen:", result.data.info.error.message) + console.error("Versuche:", result.data.info.error.retries) +} +``` + +### Best Practices + +1. **Klare Beschreibungen**: Gib in deinen Schema-Properties klare Beschreibungen an, damit das Modell versteht, welche Daten extrahiert werden sollen. +2. **`required` nutzen**: Definiere, welche Felder zwingend vorhanden sein muessen. +3. **Schemas einfach halten**: Komplexe verschachtelte Schemas sind fuer das Modell schwerer korrekt auszufuellen. +4. **`retryCount` anpassen**: Erhoehe den Wert bei komplexen Schemas, verringere ihn bei einfachen. + +--- + ## APIs Das SDK stellt alle Server-APIs ueber einen typsicheren Client bereit. @@ -127,9 +199,9 @@ Das SDK stellt alle Server-APIs ueber einen typsicheren Client bereit. ### Global -| Method | Description | Response | -| ----------------- | ------------------------------- | ------------------------------------ | -| `global.health()` | Check server health and version | `{ healthy: true, version: string }` | +| Method | Description | Response | +| ----------------- | -------------------------------- | ------------------------------------ | +| `global.health()` | Prueft Server-Status und Version | `{ healthy: true, version: string }` | --- @@ -144,10 +216,10 @@ console.log(health.data.version) ### App -| Method | Description | Response | -| -------------- | ------------------------- | ------------------------------------------- | -| `app.log()` | Write a log entry | `boolean` | -| `app.agents()` | List all available agents | Agent[] | +| Method | Description | Response | +| -------------- | -------------------------------- | ------------------------------------------- | +| `app.log()` | Schreibt einen Log-Eintrag | `boolean` | +| `app.agents()` | Listet alle verfuegbaren Agenten | Agent[] | --- @@ -171,10 +243,10 @@ const agents = await client.app.agents() ### Project -| Method | Description | Response | -| ------------------- | ------------------- | --------------------------------------------- | -| `project.list()` | List all projects | Project[] | -| `project.current()` | Get current project | Project | +| Method | Description | Response | +| ------------------- | ---------------------------- | --------------------------------------------- | +| `project.list()` | Listet alle Projekte | Project[] | +| `project.current()` | Ruft das aktuelle Projekt ab | Project | --- @@ -192,9 +264,9 @@ const currentProject = await client.project.current() ### Path -| Method | Description | Response | -| ------------ | ---------------- | ---------------------------------------- | -| `path.get()` | Get current path | Path | +| Method | Description | Response | +| ------------ | -------------------------- | ---------------------------------------- | +| `path.get()` | Ruft den aktuellen Pfad ab | Path | --- @@ -209,10 +281,10 @@ const pathInfo = await client.path.get() ### Config -| Method | Description | Response | -| -------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- | -| `config.get()` | Get config info | Config | -| `config.providers()` | List providers and default models | `{ providers: `Provider[]`, default: { [key: string]: string } }` | +| Method | Description | Response | +| -------------------- | ------------------------------------ | ----------------------------------------------------------------------------------------------------- | +| `config.get()` | Ruft Konfigurationsinfos ab | Config | +| `config.providers()` | Listet Provider und Standard-Modelle | `{ providers: `Provider[]`, default: { [key: string]: string } }` | --- @@ -228,27 +300,27 @@ const { providers, default: defaults } = await client.config.providers() ### Sessions -| Method | Description | Notes | -| ---------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | List sessions | Returns Session[] | -| `session.get({ path })` | Get session | Returns Session | -| `session.children({ path })` | List child sessions | Returns Session[] | -| `session.create({ body })` | Create session | Returns Session | -| `session.delete({ path })` | Delete session | Returns `boolean` | -| `session.update({ path, body })` | Update session properties | Returns Session | -| `session.init({ path, body })` | Analyze app and create `AGENTS.md` | Returns `boolean` | -| `session.abort({ path })` | Abort a running session | Returns `boolean` | -| `session.share({ path })` | Share session | Returns Session | -| `session.unshare({ path })` | Unshare session | Returns Session | -| `session.summarize({ path, body })` | Summarize session | Returns `boolean` | -| `session.messages({ path })` | List messages in a session | Returns `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ path })` | Get message details | Returns `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | Send prompt message | `body.noReply: true` returns UserMessage (context only). Default returns AssistantMessage with AI response | -| `session.command({ path, body })` | Send command to session | Returns `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | Run a shell command | Returns AssistantMessage | -| `session.revert({ path, body })` | Revert a message | Returns Session | -| `session.unrevert({ path })` | Restore reverted messages | Returns Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | Respond to a permission request | Returns `boolean` | +| Method | Description | Notes | +| ---------------------------------------------------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | Listet Sessions | Gibt Session[] zurueck | +| `session.get({ path })` | Ruft Session ab | Gibt Session zurueck | +| `session.children({ path })` | Listet Kind-Sessions | Gibt Session[] zurueck | +| `session.create({ body })` | Erstellt Session | Gibt Session zurueck | +| `session.delete({ path })` | Loescht Session | Gibt `boolean` zurueck | +| `session.update({ path, body })` | Aktualisiert Session-Eigenschaften | Gibt Session zurueck | +| `session.init({ path, body })` | Analysiert App und erstellt `AGENTS.md` | Gibt `boolean` zurueck | +| `session.abort({ path })` | Bricht eine laufende Session ab | Gibt `boolean` zurueck | +| `session.share({ path })` | Teilt Session | Gibt Session zurueck | +| `session.unshare({ path })` | Hebt Teilen der Session auf | Gibt Session zurueck | +| `session.summarize({ path, body })` | Fasst Session zusammen | Gibt `boolean` zurueck | +| `session.messages({ path })` | Listet Nachrichten einer Session | Gibt `{ info: `Message`, parts: `Part[]`}[]` zurueck | +| `session.message({ path })` | Ruft Nachrichtendetails ab | Gibt `{ info: `Message`, parts: `Part[]`}` zurueck | +| `session.prompt({ path, body })` | Sendet Prompt-Nachricht | `body.noReply: true` gibt UserMessage (nur Kontext) zurueck. Standard gibt AssistantMessage mit AI-Antwort zurueck. Unterstuetzt `body.outputFormat` fuer [strukturierte Ausgabe](#structured-output) | +| `session.command({ path, body })` | Sendet Befehl an Session | Gibt `{ info: `AssistantMessage`, parts: `Part[]`}` zurueck | +| `session.shell({ path, body })` | Fuehrt Shell-Befehl aus | Gibt AssistantMessage zurueck | +| `session.revert({ path, body })` | Setzt Nachricht zurueck | Gibt Session zurueck | +| `session.unrevert({ path })` | Stellt zurueckgesetzte Nachrichten wieder her | Gibt Session zurueck | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | Antwortet auf eine Berechtigungsanfrage | Gibt `boolean` zurueck | --- @@ -285,19 +357,19 @@ await client.session.prompt({ ### Files -| Method | Description | Response | -| ------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------- | -| `find.text({ query })` | Search for text in files | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | -| `find.files({ query })` | Find files and directories by name | `string[]` (paths) | -| `find.symbols({ query })` | Find workspace symbols | Symbol[] | -| `file.read({ query })` | Read a file | `{ type: "raw" \| "patch", content: string }` | -| `file.status({ query? })` | Get status for tracked files | File[] | +| Method | Description | Response | +| ------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------- | +| `find.text({ query })` | Sucht Text in Dateien | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `find.files({ query })` | Findet Dateien und Verzeichnisse nach Namen | `string[]` (paths) | +| `find.symbols({ query })` | Findet Workspace-Symbole | Symbol[] | +| `file.read({ query })` | Liest eine Datei | `{ type: "raw" \| "patch", content: string }` | +| `file.status({ query? })` | Ruft Status fuer getrackte Dateien ab | File[] | -`find.files` supports a few optional query fields: +`find.files` unterstuetzt einige optionale Query-Felder: -- `type`: `"file"` or `"directory"` -- `directory`: override the project root for the search -- `limit`: max results (1–200) +- `type`: `"file"` oder `"directory"` +- `directory`: Ueberschreibt das Projekt-Root fuer die Suche +- `limit`: Maximale Ergebnisse (1–200) --- @@ -326,17 +398,17 @@ const content = await client.file.read({ ### TUI -| Method | Description | Response | -| ------------------------------ | ------------------------- | --------- | -| `tui.appendPrompt({ body })` | Append text to the prompt | `boolean` | -| `tui.openHelp()` | Open the help dialog | `boolean` | -| `tui.openSessions()` | Open the session selector | `boolean` | -| `tui.openThemes()` | Open the theme selector | `boolean` | -| `tui.openModels()` | Open the model selector | `boolean` | -| `tui.submitPrompt()` | Submit the current prompt | `boolean` | -| `tui.clearPrompt()` | Clear the prompt | `boolean` | -| `tui.executeCommand({ body })` | Execute a command | `boolean` | -| `tui.showToast({ body })` | Show toast notification | `boolean` | +| Method | Description | Response | +| ------------------------------ | ------------------------------ | --------- | +| `tui.appendPrompt({ body })` | Haengt Text an den Prompt an | `boolean` | +| `tui.openHelp()` | Oeffnet den Hilfedialog | `boolean` | +| `tui.openSessions()` | Oeffnet die Session-Auswahl | `boolean` | +| `tui.openThemes()` | Oeffnet die Theme-Auswahl | `boolean` | +| `tui.openModels()` | Oeffnet die Modell-Auswahl | `boolean` | +| `tui.submitPrompt()` | Sendet den aktuellen Prompt ab | `boolean` | +| `tui.clearPrompt()` | Leert den Prompt | `boolean` | +| `tui.executeCommand({ body })` | Fuehrt einen Befehl aus | `boolean` | +| `tui.showToast({ body })` | Zeigt Toast-Benachrichtigung | `boolean` | --- @@ -357,9 +429,9 @@ await client.tui.showToast({ ### Auth -| Method | Description | Response | -| ------------------- | ------------------------------ | --------- | -| `auth.set({ ... })` | Set authentication credentials | `boolean` | +| Method | Description | Response | +| ------------------- | ----------------------------- | --------- | +| `auth.set({ ... })` | Setzt Authentifizierungsdaten | `boolean` | --- @@ -378,7 +450,7 @@ await client.auth.set({ | Method | Description | Response | | ------------------- | ------------------------- | ------------------------- | -| `event.subscribe()` | Server-sent events stream | Server-sent events stream | +| `event.subscribe()` | Server-Sent Events Stream | Server-sent events stream | --- diff --git a/packages/web/src/content/docs/de/server.mdx b/packages/web/src/content/docs/de/server.mdx index dd4a565faf..64322bda85 100644 --- a/packages/web/src/content/docs/de/server.mdx +++ b/packages/web/src/content/docs/de/server.mdx @@ -93,28 +93,28 @@ Der opencode-Server stellt folgende APIs bereit. ### Global -| Method | Path | Description | Response | -| ------ | ---------------- | ------------------------------ | ------------------------------------ | -| `GET` | `/global/health` | Get server health and version | `{ healthy: true, version: string }` | -| `GET` | `/global/event` | Get global events (SSE stream) | Event stream | +| Method | Path | Description | Response | +| ------ | ---------------- | ----------------------------------- | ------------------------------------ | +| `GET` | `/global/health` | Ruft Server-Status und Version ab | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | Ruft globale Events ab (SSE-Stream) | Event stream | --- ### Project -| Method | Path | Description | Response | -| ------ | ------------------ | ----------------------- | --------------------------------------------- | -| `GET` | `/project` | List all projects | Project[] | -| `GET` | `/project/current` | Get the current project | Project | +| Method | Path | Description | Response | +| ------ | ------------------ | ---------------------------- | --------------------------------------------- | +| `GET` | `/project` | Listet alle Projekte | Project[] | +| `GET` | `/project/current` | Ruft das aktuelle Projekt ab | Project | --- ### Path & VCS -| Method | Path | Description | Response | -| ------ | ------- | ------------------------------------ | ------------------------------------------- | -| `GET` | `/path` | Get the current path | Path | -| `GET` | `/vcs` | Get VCS info for the current project | VcsInfo | +| Method | Path | Description | Response | +| ------ | ------- | ------------------------------------------- | ------------------------------------------- | +| `GET` | `/path` | Ruft den aktuellen Pfad ab | Path | +| `GET` | `/vcs` | Ruft VCS-Infos fuer das aktuelle Projekt ab | VcsInfo | --- @@ -122,87 +122,87 @@ Der opencode-Server stellt folgende APIs bereit. | Method | Path | Description | Response | | ------ | ------------------- | ---------------------------- | --------- | -| `POST` | `/instance/dispose` | Dispose the current instance | `boolean` | +| `POST` | `/instance/dispose` | Beendet die aktuelle Instanz | `boolean` | --- ### Konfiguration -| Method | Path | Description | Response | -| ------- | ------------------- | --------------------------------- | ---------------------------------------------------------------------------------------- | -| `GET` | `/config` | Get config info | Config | -| `PATCH` | `/config` | Update config | Config | -| `GET` | `/config/providers` | List providers and default models | `{ providers: `Provider[]`, default: { [key: string]: string } }` | +| Method | Path | Description | Response | +| ------- | ------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | Ruft Konfigurationsinfos ab | Config | +| `PATCH` | `/config` | Aktualisiert Konfiguration | Config | +| `GET` | `/config/providers` | Listet Provider und Standard-Modelle | `{ providers: `Provider[]`, default: { [key: string]: string } }` | --- ### Anbieter -| Method | Path | Description | Response | -| ------ | -------------------------------- | ------------------------------------ | ----------------------------------------------------------------------------------- | -| `GET` | `/provider` | List all providers | `{ all: `Provider[]`, default: {...}, connected: string[] }` | -| `GET` | `/provider/auth` | Get provider authentication methods | `{ [providerID: string]: `ProviderAuthMethod[]` }` | -| `POST` | `/provider/{id}/oauth/authorize` | Authorize a provider using OAuth | ProviderAuthAuthorization | -| `POST` | `/provider/{id}/oauth/callback` | Handle OAuth callback for a provider | `boolean` | +| Method | Path | Description | Response | +| ------ | -------------------------------- | ----------------------------------------------- | ----------------------------------------------------------------------------------- | +| `GET` | `/provider` | Listet alle Provider | `{ all: `Provider[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | Ruft Authentifizierungsmethoden der Provider ab | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | Autorisiert einen Provider per OAuth | ProviderAuthAuthorization | +| `POST` | `/provider/{id}/oauth/callback` | Behandelt OAuth-Callback fuer einen Provider | `boolean` | --- ### Sitzungen -| Method | Path | Description | Notes | -| -------- | ---------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------- | -| `GET` | `/session` | List all sessions | Returns Session[] | -| `POST` | `/session` | Create a new session | body: `{ parentID?, title? }`, returns Session | -| `GET` | `/session/status` | Get session status for all sessions | Returns `{ [sessionID: string]: `SessionStatus` }` | -| `GET` | `/session/:id` | Get session details | Returns Session | -| `DELETE` | `/session/:id` | Delete a session and all its data | Returns `boolean` | -| `PATCH` | `/session/:id` | Update session properties | body: `{ title? }`, returns Session | -| `GET` | `/session/:id/children` | Get a session's child sessions | Returns Session[] | -| `GET` | `/session/:id/todo` | Get the todo list for a session | Returns Todo[] | -| `POST` | `/session/:id/init` | Analyze app and create `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returns `boolean` | -| `POST` | `/session/:id/fork` | Fork an existing session at a message | body: `{ messageID? }`, returns Session | -| `POST` | `/session/:id/abort` | Abort a running session | Returns `boolean` | -| `POST` | `/session/:id/share` | Share a session | Returns Session | -| `DELETE` | `/session/:id/share` | Unshare a session | Returns Session | -| `GET` | `/session/:id/diff` | Get the diff for this session | query: `messageID?`, returns FileDiff[] | -| `POST` | `/session/:id/summarize` | Summarize the session | body: `{ providerID, modelID }`, returns `boolean` | -| `POST` | `/session/:id/revert` | Revert a message | body: `{ messageID, partID? }`, returns `boolean` | -| `POST` | `/session/:id/unrevert` | Restore all reverted messages | Returns `boolean` | -| `POST` | `/session/:id/permissions/:permissionID` | Respond to a permission request | body: `{ response, remember? }`, returns `boolean` | +| Method | Path | Description | Notes | +| -------- | ---------------------------------------- | --------------------------------------------------- | ---------------------------------------------------------------------------------- | +| `GET` | `/session` | Listet alle Sitzungen | Gibt Session[] zurueck | +| `POST` | `/session` | Erstellt eine neue Sitzung | body: `{ parentID?, title? }`, returns Session | +| `GET` | `/session/status` | Ruft Status aller Sitzungen ab | Gibt `{ [sessionID: string]: `SessionStatus` }` zurueck | +| `GET` | `/session/:id` | Ruft Sitzungsdetails ab | Gibt Session zurueck | +| `DELETE` | `/session/:id` | Loescht eine Sitzung und alle Daten | Gibt `boolean` zurueck | +| `PATCH` | `/session/:id` | Aktualisiert Sitzungseigenschaften | body: `{ title? }`, returns Session | +| `GET` | `/session/:id/children` | Ruft Kind-Sitzungen einer Sitzung ab | Gibt Session[] zurueck | +| `GET` | `/session/:id/todo` | Ruft die Todo-Liste einer Sitzung ab | Gibt Todo[] zurueck | +| `POST` | `/session/:id/init` | Analysiert App und erstellt `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returns `boolean` | +| `POST` | `/session/:id/fork` | Forkt eine bestehende Sitzung an einer Nachricht | body: `{ messageID? }`, returns Session | +| `POST` | `/session/:id/abort` | Bricht eine laufende Sitzung ab | Gibt `boolean` zurueck | +| `POST` | `/session/:id/share` | Teilt eine Sitzung | Gibt Session zurueck | +| `DELETE` | `/session/:id/share` | Hebt Teilen einer Sitzung auf | Gibt Session zurueck | +| `GET` | `/session/:id/diff` | Ruft den Diff fuer diese Sitzung ab | query: `messageID?`, returns FileDiff[] | +| `POST` | `/session/:id/summarize` | Fasst die Sitzung zusammen | body: `{ providerID, modelID }`, returns `boolean` | +| `POST` | `/session/:id/revert` | Setzt eine Nachricht zurueck | body: `{ messageID, partID? }`, returns `boolean` | +| `POST` | `/session/:id/unrevert` | Stellt alle zurueckgesetzten Nachrichten wieder her | Gibt `boolean` zurueck | +| `POST` | `/session/:id/permissions/:permissionID` | Antwortet auf eine Berechtigungsanfrage | body: `{ response, remember? }`, returns `boolean` | --- ### Nachrichten -| Method | Path | Description | Notes | -| ------ | --------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `GET` | `/session/:id/message` | List messages in a session | query: `limit?`, returns `{ info: `Message`, parts: `Part[]`}[]` | -| `POST` | `/session/:id/message` | Send a message and wait for response | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returns `{ info: `Message`, parts: `Part[]`}` | -| `GET` | `/session/:id/message/:messageID` | Get message details | Returns `{ info: `Message`, parts: `Part[]`}` | -| `POST` | `/session/:id/prompt_async` | Send a message asynchronously (no wait) | body: same as `/session/:id/message`, returns `204 No Content` | -| `POST` | `/session/:id/command` | Execute a slash command | body: `{ messageID?, agent?, model?, command, arguments }`, returns `{ info: `Message`, parts: `Part[]`}` | -| `POST` | `/session/:id/shell` | Run a shell command | body: `{ agent, model?, command }`, returns `{ info: `Message`, parts: `Part[]`}` | +| Method | Path | Description | Notes | +| ------ | --------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GET` | `/session/:id/message` | Listet Nachrichten in einer Sitzung | query: `limit?`, returns `{ info: `Message`, parts: `Part[]`}[]` | +| `POST` | `/session/:id/message` | Sendet eine Nachricht und wartet auf Antwort | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returns `{ info: `Message`, parts: `Part[]`}` | +| `GET` | `/session/:id/message/:messageID` | Ruft Nachrichtendetails ab | Returns `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/prompt_async` | Sendet eine Nachricht asynchron (ohne Warten) | body: same as `/session/:id/message`, returns `204 No Content` | +| `POST` | `/session/:id/command` | Fuehrt einen Slash-Befehl aus | body: `{ messageID?, agent?, model?, command, arguments }`, returns `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/shell` | Fuehrt einen Shell-Befehl aus | body: `{ agent, model?, command }`, returns `{ info: `Message`, parts: `Part[]`}` | --- ### Befehle -| Method | Path | Description | Response | -| ------ | ---------- | ----------------- | --------------------------------------------- | -| `GET` | `/command` | List all commands | Command[] | +| Method | Path | Description | Response | +| ------ | ---------- | ------------------- | --------------------------------------------- | +| `GET` | `/command` | Listet alle Befehle | Command[] | --- ### Dateien -| Method | Path | Description | Response | -| ------ | ------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------- | -| `GET` | `/find?pattern=` | Search for text in files | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | -| `GET` | `/find/file?query=` | Find files and directories by name | `string[]` (paths) | -| `GET` | `/find/symbol?query=` | Find workspace symbols | Symbol[] | -| `GET` | `/file?path=` | List files and directories | FileNode[] | -| `GET` | `/file/content?path=

` | Read a file | FileContent | -| `GET` | `/file/status` | Get status for tracked files | File[] | +| Method | Path | Description | Response | +| ------ | ------------------------ | ------------------------------------------- | ------------------------------------------------------------------------------------------- | +| `GET` | `/find?pattern=` | Sucht Text in Dateien | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `GET` | `/find/file?query=` | Findet Dateien und Verzeichnisse nach Namen | `string[]` (paths) | +| `GET` | `/find/symbol?query=` | Findet Workspace-Symbole | Symbol[] | +| `GET` | `/file?path=` | Listet Dateien und Verzeichnisse | FileNode[] | +| `GET` | `/file/content?path=

` | Liest eine Datei | FileContent | +| `GET` | `/file/status` | Ruft Status fuer getrackte Dateien ab | File[] | #### `/find/file` Abfrageparameter @@ -216,71 +216,71 @@ Der opencode-Server stellt folgende APIs bereit. ### Werkzeuge (Experimentell) -| Method | Path | Description | Response | -| ------ | ------------------------------------------- | ---------------------------------------- | -------------------------------------------- | -| `GET` | `/experimental/tool/ids` | List all tool IDs | ToolIDs | -| `GET` | `/experimental/tool?provider=

&model=` | List tools with JSON schemas for a model | ToolList | +| Method | Path | Description | Response | +| ------ | ------------------------------------------- | --------------------------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | Listet alle Tool-IDs | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | Listet Tools mit JSON-Schemas fuer ein Modell | ToolList | --- ### LSP, Formatierer & MCP -| Method | Path | Description | Response | -| ------ | ------------ | -------------------------- | -------------------------------------------------------- | -| `GET` | `/lsp` | Get LSP server status | LSPStatus[] | -| `GET` | `/formatter` | Get formatter status | FormatterStatus[] | -| `GET` | `/mcp` | Get MCP server status | `{ [name: string]: `MCPStatus` }` | -| `POST` | `/mcp` | Add MCP server dynamically | body: `{ name, config }`, returns MCP status object | +| Method | Path | Description | Response | +| ------ | ------------ | -------------------------------- | -------------------------------------------------------- | +| `GET` | `/lsp` | Ruft LSP-Server-Status ab | LSPStatus[] | +| `GET` | `/formatter` | Ruft Formatter-Status ab | FormatterStatus[] | +| `GET` | `/mcp` | Ruft MCP-Server-Status ab | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | Fuegt MCP-Server dynamisch hinzu | body: `{ name, config }`, returns MCP status object | --- ### Agenten -| Method | Path | Description | Response | -| ------ | -------- | ------------------------- | ------------------------------------------- | -| `GET` | `/agent` | List all available agents | Agent[] | +| Method | Path | Description | Response | +| ------ | -------- | -------------------------------- | ------------------------------------------- | +| `GET` | `/agent` | Listet alle verfuegbaren Agenten | Agent[] | --- ### Logging -| Method | Path | Description | Response | -| ------ | ------ | ------------------------------------------------------------ | --------- | -| `POST` | `/log` | Write log entry. Body: `{ service, level, message, extra? }` | `boolean` | +| Method | Path | Description | Response | +| ------ | ------ | ----------------------------------------------------------------- | --------- | +| `POST` | `/log` | Schreibt Log-Eintrag. Body: `{ service, level, message, extra? }` | `boolean` | --- ### TUI -| Method | Path | Description | Response | -| ------ | ----------------------- | ------------------------------------------- | ---------------------- | -| `POST` | `/tui/append-prompt` | Append text to the prompt | `boolean` | -| `POST` | `/tui/open-help` | Open the help dialog | `boolean` | -| `POST` | `/tui/open-sessions` | Open the session selector | `boolean` | -| `POST` | `/tui/open-themes` | Open the theme selector | `boolean` | -| `POST` | `/tui/open-models` | Open the model selector | `boolean` | -| `POST` | `/tui/submit-prompt` | Submit the current prompt | `boolean` | -| `POST` | `/tui/clear-prompt` | Clear the prompt | `boolean` | -| `POST` | `/tui/execute-command` | Execute a command (`{ command }`) | `boolean` | -| `POST` | `/tui/show-toast` | Show toast (`{ title?, message, variant }`) | `boolean` | -| `GET` | `/tui/control/next` | Wait for the next control request | Control request object | -| `POST` | `/tui/control/response` | Respond to a control request (`{ body }`) | `boolean` | +| Method | Path | Description | Response | +| ------ | ----------------------- | ----------------------------------------------- | ---------------------- | +| `POST` | `/tui/append-prompt` | Haengt Text an den Prompt an | `boolean` | +| `POST` | `/tui/open-help` | Oeffnet den Hilfedialog | `boolean` | +| `POST` | `/tui/open-sessions` | Oeffnet die Session-Auswahl | `boolean` | +| `POST` | `/tui/open-themes` | Oeffnet die Theme-Auswahl | `boolean` | +| `POST` | `/tui/open-models` | Oeffnet die Modell-Auswahl | `boolean` | +| `POST` | `/tui/submit-prompt` | Sendet den aktuellen Prompt ab | `boolean` | +| `POST` | `/tui/clear-prompt` | Leert den Prompt | `boolean` | +| `POST` | `/tui/execute-command` | Fuehrt einen Befehl aus (`{ command }`) | `boolean` | +| `POST` | `/tui/show-toast` | Zeigt Toast (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | Wartet auf die naechste Kontrollanfrage | Control request object | +| `POST` | `/tui/control/response` | Antwortet auf eine Kontrollanfrage (`{ body }`) | `boolean` | --- ### Authentifizierung -| Method | Path | Description | Response | -| ------ | ----------- | --------------------------------------------------------------- | --------- | -| `PUT` | `/auth/:id` | Set authentication credentials. Body must match provider schema | `boolean` | +| Method | Path | Description | Response | +| ------ | ----------- | ------------------------------------------------------------------------ | --------- | +| `PUT` | `/auth/:id` | Setzt Authentifizierungsdaten. Body muss dem Provider-Schema entsprechen | `boolean` | --- ### Events -| Method | Path | Description | Response | -| ------ | -------- | ----------------------------------------------------------------------------- | ------------------------- | -| `GET` | `/event` | Server-sent events stream. First event is `server.connected`, then bus events | Server-sent events stream | +| Method | Path | Description | Response | +| ------ | -------- | ------------------------------------------------------------------------------- | ------------------------- | +| `GET` | `/event` | Server-Sent Events Stream. Erstes Event ist `server.connected`, dann Bus-Events | Server-sent events stream | --- @@ -288,4 +288,4 @@ Der opencode-Server stellt folgende APIs bereit. | Method | Path | Description | Response | | ------ | ------ | ------------------------- | --------------------------- | -| `GET` | `/doc` | OpenAPI 3.1 specification | HTML page with OpenAPI spec | +| `GET` | `/doc` | OpenAPI 3.1 Spezifikation | HTML page with OpenAPI spec | diff --git a/packages/web/src/content/docs/de/skills.mdx b/packages/web/src/content/docs/de/skills.mdx index 63dbb126bb..72fba3eb09 100644 --- a/packages/web/src/content/docs/de/skills.mdx +++ b/packages/web/src/content/docs/de/skills.mdx @@ -36,11 +36,11 @@ Globale Definitionen kommen zusaetzlich aus `~/.config/opencode/skills/*/SKILL.m Jede `SKILL.md` muss mit YAML-Frontmatter beginnen. Nur diese Felder werden ausgewertet: -- `name` (required) -- `description` (required) +- `name` (erforderlich) +- `description` (erforderlich) - `license` (optional) - `compatibility` (optional) -- `metadata` (optional, string-to-string map) +- `metadata` (optional, String-zu-String-Map) Unbekannte Frontmatter-Felder werden ignoriert. diff --git a/packages/web/src/content/docs/de/themes.mdx b/packages/web/src/content/docs/de/themes.mdx index b97816801d..f3671220f9 100644 --- a/packages/web/src/content/docs/de/themes.mdx +++ b/packages/web/src/content/docs/de/themes.mdx @@ -83,29 +83,29 @@ Damit lassen sich Themes einfach erstellen und anpassen. ### Hierarchie -Themes are loaded from multiple directories in the following order where later directories override earlier ones: +Themes werden aus mehreren Verzeichnissen in folgender Reihenfolge geladen, wobei spaetere Verzeichnisse fruehere ueberschreiben: -1. **Built-in themes** - These are embedded in the binary -2. **User config directory** - Defined in `~/.config/opencode/themes/*.json` or `$XDG_CONFIG_HOME/opencode/themes/*.json` -3. **Project root directory** - Defined in the `/.opencode/themes/*.json` -4. **Current working directory** - Defined in `./.opencode/themes/*.json` +1. **Eingebaute Themes** - Diese sind im Binary eingebettet +2. **Benutzer-Config-Verzeichnis** - Definiert in `~/.config/opencode/themes/*.json` oder `$XDG_CONFIG_HOME/opencode/themes/*.json` +3. **Projekt-Root-Verzeichnis** - Definiert in `/.opencode/themes/*.json` +4. **Aktuelles Arbeitsverzeichnis** - Definiert in `./.opencode/themes/*.json` -If multiple directories contain a theme with the same name, the theme from the directory with higher priority will be used. +Wenn mehrere Verzeichnisse ein Theme mit demselben Namen enthalten, wird das Theme aus dem Verzeichnis mit der hoeheren Prioritaet verwendet. --- ### Theme erstellen -To create a custom theme, create a JSON file in one of the theme directories. +Um ein eigenes Theme zu erstellen, lege eine JSON-Datei in einem der Theme-Verzeichnisse an. -For user-wide themes: +Fuer benutzerweite Themes: ```bash no-frame mkdir -p ~/.config/opencode/themes vim ~/.config/opencode/themes/my-theme.json ``` -And for project-specific themes. +Und fuer projektspezifische Themes: ```bash no-frame mkdir -p .opencode/themes @@ -116,34 +116,34 @@ vim .opencode/themes/my-theme.json ### JSON-Format -Themes use a flexible JSON format with support for: +Themes nutzen ein flexibles JSON-Format mit Unterstuetzung fuer: -- **Hex colors**: `"#ffffff"` -- **ANSI colors**: `3` (0-255) -- **Color references**: `"primary"` or custom definitions -- **Dark/light variants**: `{"dark": "#000", "light": "#fff"}` -- **No color**: `"none"` - Uses the terminal's default color or transparent +- **Hex-Farben**: `"#ffffff"` +- **ANSI-Farben**: `3` (0-255) +- **Farbreferenzen**: `"primary"` oder eigene Definitionen +- **Dunkel/Hell-Varianten**: `{"dark": "#000", "light": "#fff"}` +- **Keine Farbe**: `"none"` - Nutzt die Standardfarbe des Terminals oder transparent --- ### Farbdefinitionen -The `defs` section is optional and it allows you to define reusable colors that can be referenced in the theme. +Der `defs`-Abschnitt ist optional und erlaubt es dir, wiederverwendbare Farben zu definieren, die im Theme referenziert werden koennen. --- ### Terminal-Standardwerte -The special value `"none"` can be used for any color to inherit the terminal's default color. This is particularly useful for creating themes that blend seamlessly with your terminal's color scheme: +Der spezielle Wert `"none"` kann fuer jede Farbe verwendet werden, um die Standardfarbe des Terminals zu erben. Das ist besonders nuetzlich, um Themes zu erstellen, die nahtlos mit deinem Terminal-Farbschema verschmelzen: -- `"text": "none"` - Uses terminal's default foreground color -- `"background": "none"` - Uses terminal's default background color +- `"text": "none"` - Nutzt die Standard-Vordergrundfarbe des Terminals +- `"background": "none"` - Nutzt die Standard-Hintergrundfarbe des Terminals --- ### Beispiel -Here's an example of a custom theme: +Hier ist ein Beispiel fuer ein eigenes Theme: ```json title="my-theme.json" { diff --git a/packages/web/src/content/docs/de/tools.mdx b/packages/web/src/content/docs/de/tools.mdx index b7a41d87bb..0038f25184 100644 --- a/packages/web/src/content/docs/de/tools.mdx +++ b/packages/web/src/content/docs/de/tools.mdx @@ -109,7 +109,7 @@ Das Tool `write` wird ueber die Berechtigung `edit` gesteuert. ### read -Read file contents from your codebase. +Liest Dateiinhalte aus deiner Codebasis. ```json title="opencode.json" {4} { @@ -120,13 +120,13 @@ Read file contents from your codebase. } ``` -This tool reads files and returns their contents. It supports reading specific line ranges for large files. +Dieses Tool liest Dateien und gibt deren Inhalt zurueck. Es unterstuetzt das Lesen spezifischer Zeilenbereiche bei grossen Dateien. --- ### grep -Search file contents using regular expressions. +Durchsucht Dateiinhalte mit regulaeren Ausdruecken. ```json title="opencode.json" {4} { @@ -137,13 +137,13 @@ Search file contents using regular expressions. } ``` -Fast content search across your codebase. Supports full regex syntax and file pattern filtering. +Schnelle Inhaltssuche in deiner Codebasis. Unterstuetzt volle Regex-Syntax und Filterung nach Dateimustern. --- ### glob -Find files by pattern matching. +Findet Dateien per Musterabgleich. ```json title="opencode.json" {4} { @@ -154,13 +154,13 @@ Find files by pattern matching. } ``` -Search for files using glob patterns like `**/*.js` or `src/**/*.ts`. Returns matching file paths sorted by modification time. +Sucht nach Dateien mit Glob-Mustern wie `**/*.js` oder `src/**/*.ts`. Gibt passende Dateipfade sortiert nach Aenderungsdatum zurueck. --- ### list -List files and directories in a given path. +Listet Dateien und Verzeichnisse in einem Pfad auf. ```json title="opencode.json" {4} { @@ -171,16 +171,16 @@ List files and directories in a given path. } ``` -This tool lists directory contents. It accepts glob patterns to filter results. +Dieses Tool listet Verzeichnisinhalte auf. Es akzeptiert Glob-Muster zum Filtern der Ergebnisse. --- -### lsp (experimental) +### lsp (experimentell) -Interact with your configured LSP servers to get code intelligence features like definitions, references, hover info, and call hierarchy. +Interagiere mit deinen konfigurierten LSP-Servern fuer Code-Intelligence-Features wie Definitionen, Referenzen, Hover-Infos und Call-Hierarchien. :::note -This tool is only available when `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (or `OPENCODE_EXPERIMENTAL=true`). +Dieses Tool ist nur verfuegbar, wenn `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (oder `OPENCODE_EXPERIMENTAL=true`) gesetzt ist. ::: ```json title="opencode.json" {4} @@ -192,15 +192,15 @@ This tool is only available when `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (or `OPEN } ``` -Supported operations include `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls`, and `outgoingCalls`. +Unterstuetzte Operationen sind `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls` und `outgoingCalls`. -To configure which LSP servers are available for your project, see [LSP Servers](/docs/lsp). +Um verfuegbare LSP-Server fuer dein Projekt zu konfigurieren, siehe [LSP-Server](/docs/lsp). --- ### patch -Apply patches to files. +Wendet Patches auf Dateien an. ```json title="opencode.json" {4} { @@ -211,17 +211,17 @@ Apply patches to files. } ``` -This tool applies patch files to your codebase. Useful for applying diffs and patches from various sources. +Dieses Tool wendet Patch-Dateien auf deine Codebasis an. Nuetzlich fuer Diffs und Patches aus verschiedenen Quellen. :::note -The `patch` tool is controlled by the `edit` permission, which covers all file modifications (`edit`, `write`, `patch`, `multiedit`). +Das Tool `patch` wird ueber die Berechtigung `edit` gesteuert, welche alle Datei-Aenderungen abdeckt (`edit`, `write`, `patch`, `multiedit`). ::: --- ### skill -Load a [skill](/docs/skills) (a `SKILL.md` file) and return its content in the conversation. +Laedt einen [Skill](/docs/skills) (eine `SKILL.md`-Datei) und gibt dessen Inhalt in der Unterhaltung zurueck. ```json title="opencode.json" {4} { @@ -236,7 +236,7 @@ Load a [skill](/docs/skills) (a `SKILL.md` file) and return its content in the c ### todowrite -Manage todo lists during coding sessions. +Verwaltet Todo-Listen waehrend Coding-Sessions. ```json title="opencode.json" {4} { @@ -247,17 +247,17 @@ Manage todo lists during coding sessions. } ``` -Creates and updates task lists to track progress during complex operations. The LLM uses this to organize multi-step tasks. +Erstellt und aktualisiert Aufgabenlisten, um den Fortschritt bei komplexen Operationen zu verfolgen. Das LLM nutzt dies, um mehrstufige Aufgaben zu organisieren. :::note -This tool is disabled for subagents by default, but you can enable it manually. [Learn more](/docs/agents/#permissions) +Dieses Tool ist fuer Sub-Agenten standardmaessig deaktiviert, kann aber manuell aktiviert werden. [Mehr dazu](/docs/agents/#permissions) ::: --- ### todoread -Read existing todo lists. +Liest existierende Todo-Listen. ```json title="opencode.json" {4} { @@ -268,17 +268,17 @@ Read existing todo lists. } ``` -Reads the current todo list state. Used by the LLM to track what tasks are pending or completed. +Liest den aktuellen Status der Todo-Liste. Wird vom LLM genutzt, um offene oder erledigte Aufgaben zu verfolgen. :::note -This tool is disabled for subagents by default, but you can enable it manually. [Learn more](/docs/agents/#permissions) +Dieses Tool ist fuer Sub-Agenten standardmaessig deaktiviert, kann aber manuell aktiviert werden. [Mehr dazu](/docs/agents/#permissions) ::: --- ### webfetch -Fetch web content. +Ruft Webinhalte ab. ```json title="opencode.json" {4} { @@ -289,18 +289,18 @@ Fetch web content. } ``` -Allows the LLM to fetch and read web pages. Useful for looking up documentation or researching online resources. +Erlaubt dem LLM, Webseiten abzurufen und zu lesen. Nuetzlich zum Nachschlagen von Dokumentation oder fuer Online-Recherche. --- ### websearch -Search the web for information. +Durchsucht das Web nach Informationen. :::note -This tool is only available when using the OpenCode provider or when the `OPENCODE_ENABLE_EXA` environment variable is set to any truthy value (e.g., `true` or `1`). +Dieses Tool ist nur verfuegbar, wenn der OpenCode-Provider genutzt wird oder die Umgebungsvariable `OPENCODE_ENABLE_EXA` auf einen 'truthy' Wert (z. B. `true` oder `1`) gesetzt ist. -To enable when launching OpenCode: +Zum Aktivieren beim Start von OpenCode: ```bash OPENCODE_ENABLE_EXA=1 opencode @@ -317,19 +317,19 @@ OPENCODE_ENABLE_EXA=1 opencode } ``` -Performs web searches using Exa AI to find relevant information online. Useful for researching topics, finding current events, or gathering information beyond the training data cutoff. +Fuehrt Websuchen mit Exa AI durch, um relevante Informationen online zu finden. Nuetzlich fuer Recherche, aktuelle Ereignisse oder Informationen jenseits des Trainingsdatums. -No API key is required — the tool connects directly to Exa AI's hosted MCP service without authentication. +Kein API-Key erforderlich — das Tool verbindet sich direkt mit dem gehosteten MCP-Service von Exa AI ohne Authentifizierung. :::tip -Use `websearch` when you need to find information (discovery), and `webfetch` when you need to retrieve content from a specific URL (retrieval). +Nutze `websearch` zum Finden von Informationen (Discovery) und `webfetch` zum Abrufen von Inhalten einer spezifischen URL (Retrieval). ::: --- ### question -Ask the user questions during execution. +Stellt dem Benutzer waehrend der Ausfuehrung Fragen. ```json title="opencode.json" {4} { @@ -340,14 +340,14 @@ Ask the user questions during execution. } ``` -This tool allows the LLM to ask the user questions during a task. It's useful for: +Dieses Tool erlaubt dem LLM, dem Benutzer waehrend einer Aufgabe Fragen zu stellen. Nuetzlich fuer: -- Gathering user preferences or requirements -- Clarifying ambiguous instructions -- Getting decisions on implementation choices -- Offering choices about what direction to take +- Sammeln von Benutzerpraeferenzen oder Anforderungen +- Klaerung mehrdeutiger Anweisungen +- Entscheidungen bei Implementierungsoptionen einholen +- Auswahlmoeglichkeiten fuer das weitere Vorgehen anbieten -Each question includes a header, the question text, and a list of options. Users can select from the provided options or type a custom answer. When there are multiple questions, users can navigate between them before submitting all answers. +Jede Frage enthaelt eine Ueberschrift, den Fragetext und eine Liste von Optionen. Benutzer koennen aus den Optionen waehlen oder eine eigene Antwort eingeben. Bei mehreren Fragen koennen Benutzer zwischen ihnen navigieren, bevor sie alle Antworten absenden. --- diff --git a/packages/web/src/content/docs/de/troubleshooting.mdx b/packages/web/src/content/docs/de/troubleshooting.mdx index 076200cbd9..e8286faca0 100644 --- a/packages/web/src/content/docs/de/troubleshooting.mdx +++ b/packages/web/src/content/docs/de/troubleshooting.mdx @@ -12,7 +12,7 @@ Wenn OpenCode Probleme macht, starte mit Logs und lokal gespeicherten Daten auf Logdateien werden hier gespeichert: - **macOS/Linux**: `~/.local/share/opencode/log/` -- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.local\share\opencode\log` +- **Windows**: Druecke `WIN+R` und fuege ein: `%USERPROFILE%\.local\share\opencode\log` Dateinamen enthalten Zeitstempel (z. B. `2025-01-09T123456.log`) und es bleiben die letzten 10 Logs erhalten. @@ -25,7 +25,7 @@ Mit `--log-level` bekommst du detailliertere Diagnoseinfos, z. B. `opencode --lo opencode speichert Sitzungs- und App-Daten auf der Festplatte unter: - **macOS/Linux**: `~/.local/share/opencode/` -- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.local\share\opencode` +- **Windows**: Druecke `WIN+R` und fuege ein: `%USERPROFILE%\.local\share\opencode` Dieses Verzeichnis enthaelt: @@ -52,17 +52,17 @@ Viele Probleme kommen von fehlerhaften Plugins, kaputtem Cache oder falschen Ser ### Plugins deaktivieren -If the desktop app is crashing on launch, hanging, or behaving strangely, start by disabling plugins. +Wenn die Desktop-App beim Start abstuerzt, haengt oder sich seltsam verhaelt, deaktiviere zunaechst Plugins. #### Globale Konfiguration prüfen -Open your global config file and look for a `plugin` key. +Oeffne deine globale Konfigurationsdatei und suche nach dem `plugin`-Schluessel. -- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (or `~/.config/opencode/opencode.json`) -- **macOS/Linux** (older installs): `~/.local/share/opencode/opencode.jsonc` -- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.config\opencode\opencode.jsonc` +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (oder `~/.config/opencode/opencode.json`) +- **macOS/Linux** (aeltere Installationen): `~/.local/share/opencode/opencode.jsonc` +- **Windows**: Druecke `WIN+R` und fuege ein: `%USERPROFILE%\.config\opencode\opencode.jsonc` -If you have plugins configured, temporarily disable them by removing the key or setting it to an empty array: +Wenn du Plugins konfiguriert hast, deaktiviere sie voruebergehend, indem du den Schluessel entfernst oder auf ein leeres Array setzt: ```jsonc { @@ -73,100 +73,100 @@ If you have plugins configured, temporarily disable them by removing the key or #### Plugin-Verzeichnisse prüfen -OpenCode can also load local plugins from disk. Temporarily move these out of the way (or rename the folder) and restart the desktop app: +OpenCode kann auch lokale Plugins von der Festplatte laden. Verschiebe diese voruebergehend (oder benenne den Ordner um) und starte die Desktop-App neu: -- **Global plugins** +- **Globale Plugins** - **macOS/Linux**: `~/.config/opencode/plugins/` - - **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.config\opencode\plugins` -- **Project plugins** (only if you use per-project config) + - **Windows**: Druecke `WIN+R` und fuege ein: `%USERPROFILE%\.config\opencode\plugins` +- **Projekt-Plugins** (nur bei projektspezifischer Konfig) - `/.opencode/plugins/` -If the app starts working again, re-enable plugins one at a time to find which one is causing the issue. +Wenn die App wieder funktioniert, aktiviere Plugins nacheinander, um den Verursacher zu finden. --- ### Cache leeren -If disabling plugins doesn't help (or a plugin install is stuck), clear the cache so OpenCode can rebuild it. +Wenn das Deaktivieren von Plugins nicht hilft (oder eine Plugin-Installation haengt), leere den Cache, damit OpenCode ihn neu aufbauen kann. -1. Quit OpenCode Desktop completely. -2. Delete the cache directory: +1. Beende OpenCode Desktop komplett. +2. Loesche das Cache-Verzeichnis: -- **macOS**: Finder -> `Cmd+Shift+G` -> paste `~/.cache/opencode` -- **Linux**: delete `~/.cache/opencode` (or run `rm -rf ~/.cache/opencode`) -- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.cache\opencode` +- **macOS**: Finder -> `Cmd+Shift+G` -> einfuegen: `~/.cache/opencode` +- **Linux**: loesche `~/.cache/opencode` (oder fuehre aus: `rm -rf ~/.cache/opencode`) +- **Windows**: Druecke `WIN+R` und fuege ein: `%USERPROFILE%\.cache\opencode` -3. Restart OpenCode Desktop. +3. Starte OpenCode Desktop neu. --- ### Server-Verbindungsprobleme beheben -OpenCode Desktop can either start its own local server (default) or connect to a server URL you configured. +OpenCode Desktop kann entweder einen eigenen lokalen Server starten (Standard) oder sich mit einer konfigurierten Server-URL verbinden. -If you see a **"Connection Failed"** dialog (or the app never gets past the splash screen), check for a custom server URL. +Wenn du einen **"Connection Failed"**-Dialog siehst (oder die App beim Splash-Screen haengen bleibt), pruefe auf eine benutzerdefinierte Server-URL. #### Desktop-Standard-Server-URL löschen -From the Home screen, click the server name (with the status dot) to open the Server picker. In the **Default server** section, click **Clear**. +Klicke im Startbildschirm auf den Servernamen (mit dem Statuspunkt), um die Serverauswahl zu oeffnen. Klicke im Bereich **Default server** auf **Clear**. #### `server.port` / `server.hostname` aus Konfiguration entfernen -If your `opencode.json(c)` contains a `server` section, temporarily remove it and restart the desktop app. +Wenn deine `opencode.json(c)` einen `server`-Abschnitt enthaelt, entferne ihn voruebergehend und starte die Desktop-App neu. #### Umgebungsvariablen prüfen -If you have `OPENCODE_PORT` set in your environment, the desktop app will try to use that port for the local server. +Wenn du `OPENCODE_PORT` in deiner Umgebung gesetzt hast, versucht die Desktop-App diesen Port fuer den lokalen Server zu nutzen. -- Unset `OPENCODE_PORT` (or pick a free port) and restart. +- Setze `OPENCODE_PORT` zurueck (oder waehle einen freien Port) und starte neu. --- ### Linux: Wayland / X11-Probleme -On Linux, some Wayland setups can cause blank windows or compositor errors. +Unter Linux koennen manche Wayland-Setups leere Fenster oder Compositor-Fehler verursachen. -- If you're on Wayland and the app is blank/crashing, try launching with `OC_ALLOW_WAYLAND=1`. -- If that makes things worse, remove it and try launching under an X11 session instead. +- Wenn du Wayland nutzt und die App leer ist/abstuerzt, versuche den Start mit `OC_ALLOW_WAYLAND=1`. +- Wenn das es verschlimmert, entferne es und versuche den Start in einer X11-Session. --- ### Windows: WebView2-Laufzeit -On Windows, OpenCode Desktop requires the Microsoft Edge **WebView2 Runtime**. If the app opens to a blank window or won't start, install/update WebView2 and try again. +Unter Windows benoetigt OpenCode Desktop die Microsoft Edge **WebView2 Runtime**. Wenn die App ein leeres Fenster zeigt oder nicht startet, installiere/aktualisiere WebView2 und versuche es erneut. --- ### Windows: Allgemeine Performance-Probleme -If you're experiencing slow performance, file access issues, or terminal problems on Windows, try using [WSL (Windows Subsystem for Linux)](/docs/windows-wsl). WSL provides a Linux environment that works more seamlessly with OpenCode's features. +Wenn du langsame Performance, Dateizugriffsprobleme oder Terminal-Probleme unter Windows hast, versuche [WSL (Windows Subsystem for Linux)](/docs/windows-wsl). WSL bietet eine Linux-Umgebung, die nahtloser mit OpenCode-Features funktioniert. --- ### Benachrichtigungen werden nicht angezeigt -OpenCode Desktop only shows system notifications when: +OpenCode Desktop zeigt Systembenachrichtigungen nur wenn: -- notifications are enabled for OpenCode in your OS settings, and -- the app window is not focused. +- Benachrichtigungen fuer OpenCode in den OS-Einstellungen aktiviert sind, und +- das App-Fenster nicht fokussiert ist. --- ### Desktop-App-Speicher zurücksetzen (letzter Ausweg) -If the app won't start and you can't clear settings from inside the UI, reset the desktop app's saved state. +Wenn die App nicht startet und du Einstellungen nicht in der UI loeschen kannst, setze den gespeicherten Zustand der Desktop-App zurueck. -1. Quit OpenCode Desktop. -2. Find and delete these files (they live in the OpenCode Desktop app data directory): +1. Beende OpenCode Desktop. +2. Finde und loesche diese Dateien (im App-Data-Verzeichnis von OpenCode Desktop): - `opencode.settings.dat` (desktop default server URL) -- `opencode.global.dat` and `opencode.workspace.*.dat` (UI state like recent servers/projects) +- `opencode.global.dat` und `opencode.workspace.*.dat` (UI state like recent servers/projects) -To find the directory quickly: +So findest du das Verzeichnis schnell: -- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (then search for the filenames above) -- **Linux**: search under `~/.local/share` for the filenames above -- **Windows**: Press `WIN+R` -> `%APPDATA%` (then search for the filenames above) +- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (dann suche nach den Dateinamen oben) +- **Linux**: suche unter `~/.local/share` nach den Dateinamen oben +- **Windows**: Druecke `WIN+R` -> `%APPDATA%` (dann suche nach den Dateinamen oben) --- @@ -198,84 +198,83 @@ Hier sind typische Fehlerbilder und wie du sie loest. ### OpenCode startet nicht -1. Check the logs for error messages -2. Try running with `--print-logs` to see output in the terminal -3. Ensure you have the latest version with `opencode upgrade` +1. Pruefe die Logs auf Fehlermeldungen +2. Versuche den Start mit `--print-logs`, um Ausgaben im Terminal zu sehen +3. Stelle sicher, dass du die neueste Version hast: `opencode upgrade` --- ### Authentifizierungsprobleme -1. Try re-authenticating with the `/connect` command in the TUI -2. Check that your API keys are valid -3. Ensure your network allows connections to the provider's API +1. Versuche erneute Authentifizierung mit `/connect` in der TUI +2. Pruefe, ob deine API-Keys gueltig sind +3. Stelle sicher, dass dein Netzwerk Verbindungen zur Provider-API erlaubt --- ### Modell nicht verfügbar -1. Check that you've authenticated with the provider -2. Verify the model name in your config is correct -3. Some models may require specific access or subscriptions +1. Pruefe, ob du dich beim Provider authentifiziert hast +2. Verifiziere, dass der Modellname in deiner Config korrekt ist +3. Manche Modelle erfordern speziellen Zugriff oder Abonnements -If you encounter `ProviderModelNotFoundError` you are most likely incorrectly -referencing a model somewhere. -Models should be referenced like so: `/` +Wenn du `ProviderModelNotFoundError` erhaeltst, referenzierst du ein Modell wahrscheinlich falsch. +Modelle sollten so referenziert werden: `/` -Examples: +Beispiele: - `openai/gpt-4.1` - `openrouter/google/gemini-2.5-flash` - `opencode/kimi-k2` -To figure out what models you have access to, run `opencode models` +Um zu sehen, auf welche Modelle du Zugriff hast, fuehre `opencode models` aus. --- ### ProviderInitError -If you encounter a ProviderInitError, you likely have an invalid or corrupted configuration. +Wenn du einen ProviderInitError erhaeltst, hast du wahrscheinlich eine ungueltige oder korrupte Konfiguration. -To resolve this: +Zur Loesung: -1. First, verify your provider is set up correctly by following the [providers guide](/docs/providers) -2. If the issue persists, try clearing your stored configuration: +1. Pruefe zuerst, ob dein Provider korrekt eingerichtet ist, gemaess dem [Provider-Guide](/docs/providers) +2. Wenn das Problem besteht, versuche deine gespeicherte Konfiguration zu loeschen: ```bash rm -rf ~/.local/share/opencode ``` - On Windows, press `WIN+R` and delete: `%USERPROFILE%\.local\share\opencode` + Unter Windows druecke `WIN+R` und loesche: `%USERPROFILE%\.local\share\opencode` -3. Re-authenticate with your provider using the `/connect` command in the TUI. +3. Authentifiziere dich erneut beim Provider mit dem `/connect`-Befehl in der TUI. --- ### AI_APICallError und Provider-Paket-Probleme -If you encounter API call errors, this may be due to outdated provider packages. opencode dynamically installs provider packages (OpenAI, Anthropic, Google, etc.) as needed and caches them locally. +Wenn du API-Call-Fehler erhaeltst, kann das an veralteten Provider-Paketen liegen. opencode installiert Provider-Pakete (OpenAI, Anthropic, Google, etc.) dynamisch bei Bedarf und cached sie lokal. -To resolve provider package issues: +Um Provider-Paket-Probleme zu loesen: -1. Clear the provider package cache: +1. Leere den Provider-Paket-Cache: ```bash rm -rf ~/.cache/opencode ``` - On Windows, press `WIN+R` and delete: `%USERPROFILE%\.cache\opencode` + Unter Windows druecke `WIN+R` und loesche: `%USERPROFILE%\.cache\opencode` -2. Restart opencode to reinstall the latest provider packages +2. Starte opencode neu, um die neuesten Provider-Pakete zu installieren -This will force opencode to download the most recent versions of provider packages, which often resolves compatibility issues with model parameters and API changes. +Dies zwingt opencode, die neuesten Versionen der Provider-Pakete herunterzuladen, was oft Kompatibilitaetsprobleme mit Modellparametern und API-Aenderungen loest. --- ### Copy/Paste funktioniert nicht unter Linux -Linux users need to have one of the following clipboard utilities installed for copy/paste functionality to work: +Linux-Nutzer muessen eines der folgenden Clipboard-Utilities installiert haben, damit Copy/Paste funktioniert: -**For X11 systems:** +**Fuer X11-Systeme:** ```bash apt install -y xclip @@ -283,13 +282,13 @@ apt install -y xclip apt install -y xsel ``` -**For Wayland systems:** +**Fuer Wayland-Systeme:** ```bash apt install -y wl-clipboard ``` -**For headless environments:** +**Fuer Headless-Umgebungen:** ```bash apt install -y xvfb @@ -298,4 +297,4 @@ Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & export DISPLAY=:99.0 ``` -opencode will detect if you're using Wayland and prefer `wl-clipboard`, otherwise it will try to find clipboard tools in order of: `xclip` and `xsel`. +opencode erkennt, ob du Wayland nutzt und bevorzugt `wl-clipboard`, sonst versucht es `xclip` und `xsel` (in dieser Reihenfolge). diff --git a/packages/web/src/content/docs/de/tui.mdx b/packages/web/src/content/docs/de/tui.mdx index ebd16fa76a..144662c119 100644 --- a/packages/web/src/content/docs/de/tui.mdx +++ b/packages/web/src/content/docs/de/tui.mdx @@ -74,7 +74,7 @@ Hier sind alle verfuegbaren Slash-Commands: ### connect -Add a provider to OpenCode. Allows you to select from available providers and add their API keys. +Fuegt einen Provider zu OpenCode hinzu. Erlaubt die Auswahl aus verfuegbaren Providern und das Hinzufuegen ihrer API-Keys. ```bash frame="none" /connect @@ -84,7 +84,7 @@ Add a provider to OpenCode. Allows you to select from available providers and ad ### compact -Compact the current session. _Alias_: `/summarize` +Kompaktiert die aktuelle Session. _Alias_: `/summarize` ```bash frame="none" /compact @@ -96,7 +96,7 @@ Compact the current session. _Alias_: `/summarize` ### details -Toggle tool execution details. +Schaltet Tool-Ausfuehrungsdetails um. ```bash frame="none" /details @@ -108,7 +108,7 @@ Toggle tool execution details. ### editor -Open external editor for composing messages. Uses the editor set in your `EDITOR` environment variable. [Learn more](#editor-setup). +Oeffnet externen Editor zum Verfassen von Nachrichten. Nutzt den in der `EDITOR`-Umgebungsvariable gesetzten Editor. [Mehr dazu](#editor-setup). ```bash frame="none" /editor @@ -120,7 +120,7 @@ Open external editor for composing messages. Uses the editor set in your `EDITOR ### exit -Exit OpenCode. _Aliases_: `/quit`, `/q` +Beendet OpenCode. _Aliase_: `/quit`, `/q` ```bash frame="none" /exit @@ -132,7 +132,7 @@ Exit OpenCode. _Aliases_: `/quit`, `/q` ### export -Export current conversation to Markdown and open in your default editor. Uses the editor set in your `EDITOR` environment variable. [Learn more](#editor-setup). +Exportiert die aktuelle Unterhaltung als Markdown und oeffnet sie in deinem Standard-Editor. Nutzt den in der `EDITOR`-Umgebungsvariable gesetzten Editor. [Mehr dazu](#editor-setup). ```bash frame="none" /export @@ -144,7 +144,7 @@ Export current conversation to Markdown and open in your default editor. Uses th ### help -Show the help dialog. +Zeigt den Hilfedialog. ```bash frame="none" /help @@ -156,7 +156,7 @@ Show the help dialog. ### init -Create or update `AGENTS.md` file. [Learn more](/docs/rules). +Erstellt oder aktualisiert die `AGENTS.md`-Datei. [Mehr dazu](/docs/rules). ```bash frame="none" /init @@ -168,7 +168,7 @@ Create or update `AGENTS.md` file. [Learn more](/docs/rules). ### models -List available models. +Listet verfuegbare Modelle. ```bash frame="none" /models @@ -180,7 +180,7 @@ List available models. ### new -Start a new session. _Alias_: `/clear` +Startet eine neue Session. _Alias_: `/clear` ```bash frame="none" /new @@ -192,14 +192,13 @@ Start a new session. _Alias_: `/clear` ### redo -Redo a previously undone message. Only available after using `/undo`. +Wiederholt eine zuvor rueckgaengig gemachte Nachricht. Nur verfuegbar nach Verwendung von `/undo`. :::tip -Any file changes will also be restored. +Auch Dateiaenderungen werden wiederhergestellt. ::: -Internally, this uses Git to manage the file changes. So your project **needs to -be a Git repository**. +Intern nutzt dies Git, um die Dateiaenderungen zu verwalten. Dein Projekt muss also **ein Git-Repository sein**. ```bash frame="none" /redo @@ -211,7 +210,7 @@ be a Git repository**. ### sessions -List and switch between sessions. _Aliases_: `/resume`, `/continue` +Listet Sessions und wechselt zwischen ihnen. _Aliase_: `/resume`, `/continue` ```bash frame="none" /sessions @@ -223,7 +222,7 @@ List and switch between sessions. _Aliases_: `/resume`, `/continue` ### share -Share current session. [Learn more](/docs/share). +Teilt die aktuelle Session. [Mehr dazu](/docs/share). ```bash frame="none" /share @@ -235,7 +234,7 @@ Share current session. [Learn more](/docs/share). ### themes -List available themes. +Listet verfuegbare Themes. ```bash frame="none" /theme @@ -247,10 +246,10 @@ List available themes. ### thinking -Toggle the visibility of thinking/reasoning blocks in the conversation. When enabled, you can see the model's reasoning process for models that support extended thinking. +Schaltet die Sichtbarkeit von Thinking/Reasoning-Bloecken in der Unterhaltung um. Wenn aktiviert, kannst du den Denkprozess des Modells sehen (bei Modellen, die das unterstuetzen). :::note -This command only controls whether thinking blocks are **displayed** - it does not enable or disable the model's reasoning capabilities. To toggle actual reasoning capabilities, use `ctrl+t` to cycle through model variants. +Dieser Befehl steuert nur, ob Thinking-Bloecke **angezeigt** werden - er aktiviert oder deaktiviert nicht die Reasoning-Faehigkeiten des Modells. Um die Reasoning-Faehigkeiten umzuschalten, nutze `ctrl+t`, um durch die Modell-Varianten zu wechseln. ::: ```bash frame="none" @@ -261,14 +260,13 @@ This command only controls whether thinking blocks are **displayed** - it does n ### undo -Undo last message in the conversation. Removes the most recent user message, all subsequent responses, and any file changes. +Macht die letzte Nachricht in der Unterhaltung rueckgaengig. Entfernt die letzte Benutzernachricht, alle folgenden Antworten und alle Dateiaenderungen. :::tip -Any file changes made will also be reverted. +Auch durchgefuehrte Dateiaenderungen werden rueckgaengig gemacht. ::: -Internally, this uses Git to manage the file changes. So your project **needs to -be a Git repository**. +Intern nutzt dies Git, um die Dateiaenderungen zu verwalten. Dein Projekt muss also **ein Git-Repository sein**. ```bash frame="none" /undo @@ -280,7 +278,7 @@ be a Git repository**. ### unshare -Unshare current session. [Learn more](/docs/share#un-sharing). +Hebt das Teilen der aktuellen Session auf. [Mehr dazu](/docs/share#un-sharing). ```bash frame="none" /unshare @@ -290,7 +288,7 @@ Unshare current session. [Learn more](/docs/share#un-sharing). ## Editor-Einrichtung -Both the `/editor` and `/export` commands use the editor specified in your `EDITOR` environment variable. +Sowohl `/editor` als auch `/export` nutzen den in deiner `EDITOR`-Umgebungsvariable spezifizierten Editor. @@ -304,7 +302,7 @@ Both the `/editor` and `/export` commands use the editor specified in your `EDIT export EDITOR="code --wait" ``` - To make it permanent, add this to your shell profile; + Um es dauerhaft zu machen, fuege dies zu deinem Shell-Profil hinzu; `~/.bashrc`, `~/.zshrc`, etc. @@ -318,8 +316,7 @@ Both the `/editor` and `/export` commands use the editor specified in your `EDIT set EDITOR=code --wait ``` - To make it permanent, use **System Properties** > **Environment - Variables**. + Um es dauerhaft zu machen, nutze **Systemeigenschaften** > **Umgebungsvariablen**. @@ -332,62 +329,72 @@ Both the `/editor` and `/export` commands use the editor specified in your `EDIT $env:EDITOR = "code --wait" ``` - To make it permanent, add this to your PowerShell profile. + Um es dauerhaft zu machen, fuege dies zu deinem PowerShell-Profil hinzu. -Popular editor options include: +Beliebte Editoren sind: - `code` - Visual Studio Code - `cursor` - Cursor - `windsurf` - Windsurf -- `nvim` - Neovim editor -- `vim` - Vim editor -- `nano` - Nano editor +- `nvim` - Neovim +- `vim` - Vim +- `nano` - Nano - `notepad` - Windows Notepad - `subl` - Sublime Text :::note -Some editors like VS Code need to be started with the `--wait` flag. +Einige Editoren wie VS Code muessen mit dem `--wait`-Flag gestartet werden. ::: -Some editors need command-line arguments to run in blocking mode. The `--wait` flag makes the editor process block until closed. +Einige Editoren benoetigen Befehlszeilenargumente, um im blockierenden Modus zu laufen. Das `--wait`-Flag sorgt dafuer, dass der Editor-Prozess blockiert, bis er geschlossen wird. --- ## Konfiguration -You can customize TUI behavior through your OpenCode config file. +Du kannst das Verhalten der TUI ueber die Datei `tui.json` (oder `tui.jsonc`) anpassen. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +Dies ist getrennt von `opencode.json`, welche das Server-/Runtime-Verhalten konfiguriert. + ### Optionen -- `scroll_acceleration` - Enable macOS-style scroll acceleration for smooth, natural scrolling. When enabled, scroll speed increases with rapid scrolling gestures and stays precise for slower movements. **This setting takes precedence over `scroll_speed` and overrides it when enabled.** -- `scroll_speed` - Controls how fast the TUI scrolls when using scroll commands (minimum: `1`). Defaults to `3`. **Note: This is ignored if `scroll_acceleration.enabled` is set to `true`.** +- `theme` - Setzt dein UI-Theme. [Mehr dazu](/docs/themes). +- `keybinds` - Passt Tastenkombinationen an. [Mehr dazu](/docs/keybinds). +- `scroll_acceleration.enabled` - Aktiviert Scroll-Beschleunigung im macOS-Stil fuer weiches, natuerliches Scrollen. Wenn aktiviert, erhoeht sich die Scroll-Geschwindigkeit bei schnellen Gesten und bleibt praezise bei langsamen Bewegungen. **Diese Einstellung hat Vorrang vor `scroll_speed` und ueberschreibt es, wenn aktiviert.** +- `scroll_speed` - Steuert, wie schnell die TUI scrollt (Minimum: `0.001`, unterstuetzt Dezimalwerte). Standard ist `3`. **Hinweis: Wird ignoriert, wenn `scroll_acceleration.enabled` auf `true` gesetzt ist.** +- `diff_style` - Steuert die Diff-Darstellung. `"auto"` passt sich der Terminalbreite an, `"stacked"` zeigt immer ein einspaltiges Layout. + +Verwende `OPENCODE_TUI_CONFIG`, um einen benutzerdefinierten TUI-Konfigurationspfad zu laden. --- ## Anpassung -You can customize various aspects of the TUI view using the command palette (`ctrl+x h` or `/help`). These settings persist across restarts. +Du kannst verschiedene Aspekte der TUI-Ansicht ueber die Befehlspalette (`ctrl+x h` oder `/help`) anpassen. Diese Einstellungen bleiben ueber Neustarts hinweg erhalten. --- #### Benutzername-Anzeige -Toggle whether your username appears in chat messages. Access this through: +Schaltet um, ob dein Benutzername in Chat-Nachrichten erscheint. Zugriff hierueber: -- Command palette: Search for "username" or "hide username" -- The setting persists automatically and will be remembered across TUI sessions +- Befehlspalette: Suche nach "username" oder "hide username" +- Die Einstellung wird automatisch gespeichert und bleibt ueber TUI-Sessions hinweg erhalten. diff --git a/packages/web/src/content/docs/de/zen.mdx b/packages/web/src/content/docs/de/zen.mdx index f52ed5f363..7545b10deb 100644 --- a/packages/web/src/content/docs/de/zen.mdx +++ b/packages/web/src/content/docs/de/zen.mdx @@ -57,6 +57,7 @@ Du kannst unsere Modelle auch ueber die folgenden API-Endpunkte aufrufen. | Model | Model ID | Endpoint | AI SDK Package | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -66,22 +67,24 @@ Du kannst unsere Modelle auch ueber die folgenden API-Endpunkte aufrufen. | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -110,29 +113,34 @@ Unten siehst du die Preise **pro 1 Mio. Tokens**. | Model | Input | Output | Cached Read | Cached Write | | --------------------------------- | ------ | ------ | ----------- | ------------ | | Big Pickle | Free | Free | Free | - | -| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.5 Free | Free | Free | Free | - | +| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | - | | MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | -| GLM 4.7 Free | Free | Free | Free | - | +| GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 Free | Free | Free | Free | - | | Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - | +| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Claude Sonnet 4.6 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.6 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4.5 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | -| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - | @@ -152,10 +160,8 @@ Kreditkartengebuehren geben wir zum Selbstkostenpreis weiter (4,4 % + $0.30 pro Die kostenlosen Modelle: -- GLM 4.7 Free ist fuer begrenzte Zeit verfuegbar, um Feedback zu sammeln und das Modell zu verbessern. -- Kimi K2.5 Free ist fuer begrenzte Zeit verfuegbar, um Feedback zu sammeln und das Modell zu verbessern. -- MiniMax M2.1 Free ist fuer begrenzte Zeit verfuegbar, um Feedback zu sammeln und das Modell zu verbessern. -- Big Pickle ist ein Stealth-Modell und ebenfalls zeitlich begrenzt kostenlos verfuegbar. +- MiniMax M2.5 Free ist fuer begrenzte Zeit auf OpenCode verfuegbar. Das Team nutzt diese Zeit, um Feedback zu sammeln und das Modell zu verbessern. +- Big Pickle ist ein Stealth-Modell, das fuer begrenzte Zeit kostenlos auf OpenCode verfuegbar ist. Das Team nutzt diese Zeit, um Feedback zu sammeln und das Modell zu verbessern. Wenn du Fragen hast, kontaktiere uns. @@ -183,12 +189,10 @@ Mit aktiviertem Auto-Reload kann die Abrechnung dennoch darueber liegen, falls d Alle Modelle werden in den USA gehostet. Unsere Provider arbeiten grundsaetzlich mit Zero-Retention und nutzen deine Daten nicht zum Training, mit folgenden Ausnahmen: -- Big Pickle: During its free period, collected data may be used to improve the model. -- GLM 4.7 Free: During its free period, collected data may be used to improve the model. -- Kimi K2.5 Free: During its free period, collected data may be used to improve the model. -- MiniMax M2.1 Free: During its free period, collected data may be used to improve the model. -- OpenAI APIs: Requests are retained for 30 days in accordance with [OpenAI's Data Policies](https://platform.openai.com/docs/guides/your-data). -- Anthropic APIs: Requests are retained for 30 days in accordance with [Anthropic's Data Policies](https://docs.anthropic.com/en/docs/claude-code/data-usage). +- Big Pickle: Waehrend der kostenlosen Phase koennen gesammelte Daten zur Verbesserung des Modells genutzt werden. +- MiniMax M2.5 Free: Waehrend der kostenlosen Phase koennen gesammelte Daten zur Verbesserung des Modells genutzt werden. +- OpenAI APIs: Anfragen werden fuer 30 Tage gemaess [OpenAI's Data Policies](https://platform.openai.com/docs/guides/your-data) aufbewahrt. +- Anthropic APIs: Anfragen werden fuer 30 Tage gemaess [Anthropic's Data Policies](https://docs.anthropic.com/en/docs/claude-code/data-usage) aufbewahrt. --- @@ -232,8 +236,7 @@ Du kannst eigene OpenAI- oder Anthropic-API-Keys verwenden und trotzdem andere Z Bei eigenen Keys erfolgt die Token-Abrechnung direkt ueber den Provider, nicht ueber Zen. -For example, your organization might already have a key for OpenAI or Anthropic -and you want to use that instead of the one that Zen provides. +Zum Beispiel hat deine Organisation vielleicht bereits einen Key fuer OpenAI oder Anthropic und du moechtest diesen anstelle des von Zen bereitgestellten nutzen. --- diff --git a/packages/web/src/content/docs/ecosystem.mdx b/packages/web/src/content/docs/ecosystem.mdx index 0645d5eb3c..6fafc89fe6 100644 --- a/packages/web/src/content/docs/ecosystem.mdx +++ b/packages/web/src/content/docs/ecosystem.mdx @@ -26,6 +26,7 @@ You can also check out [awesome-opencode](https://github.com/awesome-opencode/aw | [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Multi-branch devcontainer isolation with shallow clones and auto-assigned ports | | [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Google Antigravity OAuth Plugin, with support for Google Search, and more robust API handling | | [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Optimize token usage by pruning obsolete tool outputs | +| [opencode-vibeguard](https://github.com/inkdust2021/opencode-vibeguard) | Redact secrets/PII into VibeGuard-style placeholders before LLM calls; restore locally | | [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Add native websearch support for supported providers with Google grounded style | | [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Enables AI agents to run background processes in a PTY, send interactive input to them. | | [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Instructions for non-interactive shell commands - prevents hangs from TTY-dependent operations | diff --git a/packages/web/src/content/docs/es/custom-tools.mdx b/packages/web/src/content/docs/es/custom-tools.mdx index 76188e184e..133abf4ab2 100644 --- a/packages/web/src/content/docs/es/custom-tools.mdx +++ b/packages/web/src/content/docs/es/custom-tools.mdx @@ -79,6 +79,32 @@ Esto crea dos herramientas: `math_add` y `math_multiply`. --- +#### Colisiones de nombres con herramientas integradas + +Las herramientas personalizadas están codificadas por el nombre de la herramienta. Si una herramienta personalizada utiliza el mismo nombre que una herramienta integrada, la herramienta personalizada tiene prioridad. + +Por ejemplo, este archivo reemplaza la herramienta `bash` integrada: + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +Prefiera nombres únicos a menos que intencionalmente desee reemplazar una herramienta integrada. Si desea deshabilitar una herramienta integrada pero no anularla, use [permisos](/docs/permissions). +::: + +--- + ### Argumentos Puedes usar `tool.schema`, que es simplemente [Zod](https://zod.dev), para definir tipos de argumentos. diff --git a/packages/web/src/content/docs/es/go.mdx b/packages/web/src/content/docs/es/go.mdx new file mode 100644 index 0000000000..49e6d585fd --- /dev/null +++ b/packages/web/src/content/docs/es/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: Suscripción de bajo coste para modelos de código abiertos. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go es una suscripción de bajo coste de **10 $/mes** que te ofrece acceso fiable a modelos populares de código abierto. + +:::note +OpenCode Go está actualmente en beta. +::: + +Go funciona como cualquier otro proveedor en OpenCode. Te suscribes a OpenCode Go y obtienes tu clave API. Es **completamente opcional** y no necesitas usarlo para utilizar OpenCode. + +Está diseñado principalmente para usuarios internacionales, con modelos alojados en EE. UU., la UE y Singapur para un acceso global estable. + +--- + +## Contexto + +Los modelos abiertos han mejorado mucho. Ahora alcanzan un rendimiento cercano al de los modelos propietarios para tareas de programación. Y como muchos proveedores pueden servirlos de forma competitiva, suelen ser mucho más baratos. + +Sin embargo, conseguir un acceso fiable y de baja latencia a ellos puede ser difícil. Los proveedores varían en calidad y disponibilidad. + +:::tip +Hemos probado un grupo selecto de modelos y proveedores que funcionan bien con OpenCode. +::: + +Para solucionar esto, hicimos un par de cosas: + +1. Probamos un grupo selecto de modelos abiertos y hablamos con sus equipos sobre la mejor manera de ejecutarlos. +2. Luego trabajamos con algunos proveedores para asegurarnos de que se sirvieran correctamente. +3. Finalmente, evaluamos la combinación de modelo/proveedor y elaboramos una lista que nos sentimos cómodos recomendando. + +OpenCode Go te da acceso a estos modelos por **10 $/mes**. + +--- + +## Cómo funciona + +OpenCode Go funciona como cualquier otro proveedor en OpenCode. + +1. Inicias sesión en **OpenCode Zen**, te suscribes a Go y copias tu clave API. +2. Ejecutas el comando `/connect` en la TUI, seleccionas `OpenCode Go` y pegas tu clave API. +3. Ejecuta `/models` en la TUI para ver la lista de modelos disponibles a través de Go. + +:::note +Solo un miembro por espacio de trabajo puede suscribirse a OpenCode Go. +::: + +La lista actual de modelos incluye: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +La lista de modelos puede cambiar a medida que probamos y añadimos nuevos. + +--- + +## Límites de uso + +OpenCode Go incluye los siguientes límites: + +- **Límite de 5 horas** — 12 $ de uso +- **Límite semanal** — 30 $ de uso +- **Límite mensual** — 60 $ de uso + +Los límites se definen en valor monetario. Esto significa que tu recuento real de solicitudes depende del modelo que uses. Los modelos más baratos como MiniMax M2.5 permiten más solicitudes, mientras que los modelos de mayor coste como GLM-5 permiten menos. + +La siguiente tabla proporciona una estimación del recuento de solicitudes basada en patrones de uso típicos de Go: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ----------------------- | ----- | --------- | ------------ | +| solicitudes por 5 horas | 1.150 | 1.850 | 30.000 | +| solicitudes por semana | 2.880 | 4.630 | 75.000 | +| solicitudes por mes | 5.750 | 9.250 | 150.000 | + +Las estimaciones se basan en patrones de solicitud promedio observados: + +- GLM-5 — 700 de entrada, 52.000 en caché, 150 tokens de salida por solicitud +- Kimi K2.5 — 870 de entrada, 55.000 en caché, 200 tokens de salida por solicitud +- MiniMax M2.5 — 300 de entrada, 55.000 en caché, 125 tokens de salida por solicitud + +Puedes realizar un seguimiento de tu uso actual en la **consola**. + +:::tip +Si alcanzas el límite de uso, puedes seguir usando los modelos gratuitos. +::: + +Los límites de uso pueden cambiar a medida que aprendamos del uso temprano y los comentarios. + +--- + +### Precios + +OpenCode Go es un plan de suscripción de **10 $/mes**. A continuación se muestran los precios **por 1M de tokens**. + +| Modelo | Entrada | Salida | Lectura en caché | +| ------------ | ------- | ------ | ---------------- | +| GLM-5 | 1,00 $ | 3,20 $ | 0,20 $ | +| Kimi K2.5 | 0,60 $ | 3,00 $ | 0,10 $ | +| MiniMax M2.5 | 0,30 $ | 1,20 $ | 0,03 $ | + +--- + +### Uso más allá de los límites + +Si también tienes créditos en tu saldo de Zen, puedes habilitar la opción **Usar saldo** en la consola. Cuando está habilitada, Go recurrirá a tu saldo de Zen después de que hayas alcanzado tus límites de uso en lugar de bloquear las solicitudes. + +--- + +## Endpoints + +También puedes acceder a los modelos de Go a través de los siguientes endpoints de API. + +| Modelo | ID del modelo | Endpoint | Paquete AI SDK | +| ------------ | ------------- | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +El [model id](/docs/config/#models) en tu configuración de OpenCode usa el formato `opencode-go/`. Por ejemplo, para Kimi K2.5, usarías `opencode-go/kimi-k2.5` en tu configuración. + +--- + +## Privacidad + +El plan está diseñado principalmente para usuarios internacionales, con modelos alojados en EE. UU., la UE y Singapur para un acceso global estable. + +Contáctanos si tienes alguna pregunta. + +--- + +## Objetivos + +Creamos OpenCode Go para: + +1. Hacer que la programación con IA sea **accesible** a más personas con una suscripción de bajo coste. +2. Proporcionar acceso **fiable** a los mejores modelos de código abierto. +3. Seleccionar modelos que han sido **probados y evaluados** para su uso con agentes de programación. +4. **Sin ataduras**, permitiéndote usar cualquier otro proveedor con OpenCode también. diff --git a/packages/web/src/content/docs/es/keybinds.mdx b/packages/web/src/content/docs/es/keybinds.mdx index 7ce014f0a2..d4880db2fa 100644 --- a/packages/web/src/content/docs/es/keybinds.mdx +++ b/packages/web/src/content/docs/es/keybinds.mdx @@ -3,11 +3,11 @@ title: Combinaciones de teclas description: Personaliza tus combinaciones de teclas. --- -OpenCode tiene una lista de combinaciones de teclas que puede personalizar a través de la configuración OpenCode. +OpenCode tiene una lista de combinaciones de teclas que puede personalizar a través de `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -117,11 +117,11 @@ No es necesario utilizar una tecla líder para las combinaciones de teclas, pero ## Desactivar combinación de teclas -Puede deshabilitar una combinación de teclas agregando la clave a su configuración con un valor de "ninguno". +Puede deshabilitar una combinación de teclas agregando la clave a `tui.json` con un valor de "none". -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/es/lsp.mdx b/packages/web/src/content/docs/es/lsp.mdx index fc741ca898..27eab4cadf 100644 --- a/packages/web/src/content/docs/es/lsp.mdx +++ b/packages/web/src/content/docs/es/lsp.mdx @@ -27,6 +27,7 @@ OpenCode viene con varios servidores LSP integrados para idiomas populares: | gopls | .go | Comando `go` disponible | | hls | .hs, .lhs | Comando `haskell-language-server-wrapper` disponible | | jdtls | .java | `Java SDK (version 21+)` instalado | +| julials | .jl | `julia` y `LanguageServer.jl` instalados | | kotlin-ls | .kt, .kts | Autoinstalaciones para proyectos Kotlin | | lua-ls | .lua | Autoinstalaciones para proyectos Lua | | nixd | .nix | Comando `nixd` disponible | diff --git a/packages/web/src/content/docs/es/plugins.mdx b/packages/web/src/content/docs/es/plugins.mdx index 904821bdb8..dc44180725 100644 --- a/packages/web/src/content/docs/es/plugins.mdx +++ b/packages/web/src/content/docs/es/plugins.mdx @@ -308,6 +308,10 @@ El ayudante `tool` crea una herramienta personalizada a la que opencode puede ll Sus herramientas personalizadas estarán disponibles para opencode junto con las herramientas integradas. +:::note +Si una herramienta de complemento utiliza el mismo nombre que una herramienta integrada, la herramienta de complemento tiene prioridad. +::: + --- ### Registro diff --git a/packages/web/src/content/docs/es/providers.mdx b/packages/web/src/content/docs/es/providers.mdx index 8d86612538..2ee033f00d 100644 --- a/packages/web/src/content/docs/es/providers.mdx +++ b/packages/web/src/content/docs/es/providers.mdx @@ -84,6 +84,38 @@ Funciona como cualquier otro proveedor en OpenCode y su uso es completamente opc --- +## OpenCode Go + +OpenCode Go es un plan de suscripción de bajo costo que brinda acceso confiable a modelos de codificación abiertos populares proporcionados por el equipo de OpenCode que han sido +probado y verificado para funcionar bien con OpenCode. + +1. Ejecute el comando `/connect` en TUI, seleccione `OpenCode Go` y diríjase a [opencode.ai/auth](https://opencode.ai/zen). + + ```txt + /connect + ``` + +2. Inicie sesión, agregue sus datos de facturación y copie su clave API. + +3. Pegue su clave API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute `/models` en TUI para ver la lista de modelos que recomendamos. + + ```txt + /models + ``` + +Funciona como cualquier otro proveedor en OpenCode y su uso es completamente opcional. + +--- + ## Directorio Veamos algunos de los proveedores en detalle. Si desea agregar un proveedor a la @@ -792,8 +824,6 @@ Para utilizar su suscripción GitHub Copilot con opencode: :::note Algunos modelos pueden necesitar un [Pro+ suscripción](https://github.com/features/copilot/plans) para usar. - -Algunos modelos deben habilitarse manualmente en su [GitHub configuración del copiloto](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use). ::: 1. Ejecute el comando `/connect` y busque GitHub Copilot. @@ -1483,6 +1513,39 @@ SAP AI Core brinda acceso a más de 40 modelos de OpenAI, Anthropic, Google, Ama --- +### STACKIT + +STACKIT AI Model Serving proporciona un entorno de alojamiento soberano totalmente gestionado para modelos de IA, centrándose en LLM como Llama, Mistral y Qwen, con máxima soberanía de datos en infraestructura europea. + +1. Diríjase al [Portal STACKIT](https://portal.stackit.cloud), navegue hasta **AI Model Serving** y cree un token de autenticación para su proyecto. + + :::tip + Necesita una cuenta de cliente STACKIT, una cuenta de usuario y un proyecto antes de crear tokens de autenticación. + ::: + +2. Ejecute el comando `/connect` y busque **STACKIT**. + + ```txt + /connect + ``` + +3. Ingrese su token de autenticación de STACKIT AI Model Serving. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Ejecute el comando `/models` para seleccionar entre los modelos disponibles como _Qwen3-VL 235B_ o _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + ### OVHcloud AI Endpoints 1. Dirígete al [panel de OVHcloud](https://ovh.com/manager). Navegue a la sección `Public Cloud`, `AI & Machine Learning` > `AI Endpoints` y en la pestaña `API Keys`, haga clic en **Crear una nueva clave API**. diff --git a/packages/web/src/content/docs/es/sdk.mdx b/packages/web/src/content/docs/es/sdk.mdx index d1282b95e9..d75149cde8 100644 --- a/packages/web/src/content/docs/es/sdk.mdx +++ b/packages/web/src/content/docs/es/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## Salida Estructurada + +Puede solicitar una salida JSON estructurada del modelo especificando un `format` con un esquema JSON. El modelo utilizará una herramienta `StructuredOutput` para devolver un JSON validado que coincida con su esquema. + +### Uso Básico + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Access the structured output +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### Tipos de Formato de Salida + +| Tipo | Descripción | +| ------------- | --------------------------------------------------------------------- | +| `text` | Predeterminado. Respuesta de texto estándar (sin salida estructurada) | +| `json_schema` | Devuelve JSON validado que coincide con el esquema proporcionado | + +### Formato de Esquema JSON + +Cuando use `type: 'json_schema'`, proporcione: + +| Campo | Tipo | Descripción | +| ------------ | --------------- | ---------------------------------------------------------------- | +| `type` | `'json_schema'` | Requerido. Especifica el modo de esquema JSON | +| `schema` | `object` | Requerido. Objeto JSON Schema que define la estructura de salida | +| `retryCount` | `number` | Opcional. Número de reintentos de validación (predeterminado: 2) | + +### Manejo de Errores + +Si el modelo no logra producir una salida estructurada válida después de todos los reintentos, la respuesta incluirá un `StructuredOutputError`: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### Mejores Prácticas + +1. **Proporcione descripciones claras** en las propiedades de su esquema para ayudar al modelo a entender qué datos extraer +2. **Use `required`** para especificar qué campos deben estar presentes +3. **Mantenga los esquemas enfocados** - los esquemas anidados complejos pueden ser más difíciles de completar correctamente para el modelo +4. **Establezca un `retryCount` apropiado** - aumente para esquemas complejos, disminuya para simples + +--- + ## API El SDK expone todas las API del servidor a través de un cliente con seguridad de tipos. @@ -226,27 +298,27 @@ const { providers, default: defaults } = await client.config.providers() ### Sesiones -| Método | Descripción | Notas | -| ---------------------------------------------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | Listar sesiones | Devuelve Session[] | -| `session.get({ path })` | Obtener sesión | Devuelve Session | -| `session.children({ path })` | Listar sesiones secundarias | Devuelve Session[] | -| `session.create({ body })` | Crear sesión | Devuelve Session | -| `session.delete({ path })` | Eliminar sesión | Devuelve `boolean` | -| `session.update({ path, body })` | Actualizar propiedades de sesión | Devuelve Session | -| `session.init({ path, body })` | Analizar aplicación y crear `AGENTS.md` | Devuelve `boolean` | -| `session.abort({ path })` | Cancelar una sesión en ejecución | Devuelve `boolean` | -| `session.share({ path })` | Compartir sesión | Devuelve Session | -| `session.unshare({ path })` | Dejar de compartir sesión | Devuelve Session | -| `session.summarize({ path, body })` | Resumir sesión | Devuelve `boolean` | -| `session.messages({ path })` | Listar mensajes en una sesión | Devuelve `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ path })` | Obtener detalles del mensaje | Devuelve `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | Enviar mensaje rápido | `body.noReply: true` devuelve UserMessage (solo contexto). El valor predeterminado devuelve AssistantMessage con respuesta de IA | -| `session.command({ path, body })` | Enviar comando a la sesión | Devuelve `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | Ejecute un comando de shell | Devuelve AssistantMessage | -| `session.revert({ path, body })` | Revertir un mensaje | Devuelve Session | -| `session.unrevert({ path })` | Restaurar mensajes revertidos | Devuelve Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | Responder a una solicitud de permiso | Devuelve `boolean` | +| Método | Descripción | Notas | +| ---------------------------------------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | Listar sesiones | Devuelve Session[] | +| `session.get({ path })` | Obtener sesión | Devuelve Session | +| `session.children({ path })` | Listar sesiones secundarias | Devuelve Session[] | +| `session.create({ body })` | Crear sesión | Devuelve Session | +| `session.delete({ path })` | Eliminar sesión | Devuelve `boolean` | +| `session.update({ path, body })` | Actualizar propiedades de sesión | Devuelve Session | +| `session.init({ path, body })` | Analizar aplicación y crear `AGENTS.md` | Devuelve `boolean` | +| `session.abort({ path })` | Cancelar una sesión en ejecución | Devuelve `boolean` | +| `session.share({ path })` | Compartir sesión | Devuelve Session | +| `session.unshare({ path })` | Dejar de compartir sesión | Devuelve Session | +| `session.summarize({ path, body })` | Resumir sesión | Devuelve `boolean` | +| `session.messages({ path })` | Listar mensajes en una sesión | Devuelve `{ info: `Message`, parts: `Part[]`}[]` | +| `session.message({ path })` | Obtener detalles del mensaje | Devuelve `{ info: `Message`, parts: `Part[]`}` | +| `session.prompt({ path, body })` | Enviar mensaje rápido | `body.noReply: true` devuelve UserMessage (solo contexto). El valor predeterminado devuelve AssistantMessage con respuesta de IA. Admite `body.outputFormat` para [salida estructurada](#salida-estructurada) | +| `session.command({ path, body })` | Enviar comando a la sesión | Devuelve `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `session.shell({ path, body })` | Ejecute un comando de shell | Devuelve AssistantMessage | +| `session.revert({ path, body })` | Revertir un mensaje | Devuelve Session | +| `session.unrevert({ path })` | Restaurar mensajes revertidos | Devuelve Session | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | Responder a una solicitud de permiso | Devuelve `boolean` | --- diff --git a/packages/web/src/content/docs/es/themes.mdx b/packages/web/src/content/docs/es/themes.mdx index d7c7426267..8c8028eb6e 100644 --- a/packages/web/src/content/docs/es/themes.mdx +++ b/packages/web/src/content/docs/es/themes.mdx @@ -61,11 +61,11 @@ El tema del sistema es para usuarios que: ## Usar un tema -Puede seleccionar un tema abriendo la selección de tema con el comando `/theme`. O puede especificarlo en su [config](/docs/config). +Puede seleccionar un tema abriendo la selección de tema con el comando `/theme`. O puede especificarlo en `tui.json`. -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` diff --git a/packages/web/src/content/docs/es/tui.mdx b/packages/web/src/content/docs/es/tui.mdx index ba7430f502..02f14d55ad 100644 --- a/packages/web/src/content/docs/es/tui.mdx +++ b/packages/web/src/content/docs/es/tui.mdx @@ -355,24 +355,34 @@ Algunos editores necesitan argumentos de línea de comandos para ejecutarse en m ## Configurar -Puede personalizar el comportamiento de TUI a través de su archivo de configuración OpenCode. +Puede personalizar el comportamiento de TUI a través de `tui.json` (o `tui.jsonc`). -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +Esto es independiente de `opencode.json`, que configura el comportamiento del servidor/tiempo de ejecución. + ### Opciones -- `scroll_acceleration`: habilite la aceleración de desplazamiento estilo macOS para un desplazamiento suave y natural. Cuando está habilitado, la velocidad de desplazamiento aumenta con gestos de desplazamiento rápido y se mantiene precisa para movimientos más lentos. **Esta configuración tiene prioridad sobre `scroll_speed` y la anula cuando está habilitada.** -- `scroll_speed`: controla la rapidez con la que se desplaza el TUI cuando se utilizan comandos de desplazamiento (mínimo: `1`). El valor predeterminado es `3`. **Nota: Esto se ignora si `scroll_acceleration.enabled` está configurado en `true`.** +- `theme`: establece su tema de interfaz de usuario. [Más información](/docs/themes). +- `keybinds`: personaliza los atajos de teclado. [Más información](/docs/keybinds). +- `scroll_acceleration.enabled`: habilite la aceleración de desplazamiento estilo macOS para un desplazamiento suave y natural. Cuando está habilitado, la velocidad de desplazamiento aumenta con gestos de desplazamiento rápido y se mantiene precisa para movimientos más lentos. **Esta configuración tiene prioridad sobre `scroll_speed` y la anula cuando está habilitada.** +- `scroll_speed`: controla la rapidez con la que se desplaza el TUI cuando se utilizan comandos de desplazamiento (mínimo: `0.001`, admite valores decimales). El valor predeterminado es `3`. **Nota: Esto se ignora si `scroll_acceleration.enabled` está configurado en `true`.** +- `diff_style`: controla la representación de diferencias. `"auto"` se adapta al ancho del terminal, `"stacked"` siempre muestra un diseño de una sola columna. + +Utilice `OPENCODE_TUI_CONFIG` para cargar una ruta de configuración de TUI personalizada. --- diff --git a/packages/web/src/content/docs/es/zen.mdx b/packages/web/src/content/docs/es/zen.mdx index 10847b452e..94838902a5 100644 --- a/packages/web/src/content/docs/es/zen.mdx +++ b/packages/web/src/content/docs/es/zen.mdx @@ -62,6 +62,7 @@ También puede acceder a nuestros modelos a través de los siguientes puntos fin | Modelo | Model ID | Endpoint | AI SDK package | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -71,22 +72,24 @@ También puede acceder a nuestros modelos a través de los siguientes puntos fin | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -115,29 +118,34 @@ Apoyamos un modelo de pago por uso. A continuación se muestran los precios **po | Modelo | Entrada | Salida | Lectura en caché | Escritura en caché | | ------------------------------------ | ------- | ------ | ---------------- | ------------------ | | Big Pickle | Gratis | Gratis | Gratis | - | -| MiniMax M2.1 Free | Gratis | Gratis | Gratis | - | +| MiniMax M2.5 Free | Gratis | Gratis | Gratis | - | +| MiniMax M2.5 | $0,30 | $1,20 | $0,06 | - | | MiniMax M2.1 | $0,30 | $1,20 | $0,10 | - | -| GLM 4.7 Free | Gratis | Gratis | Gratis | - | +| GLM 5 | $1,00 | $3,20 | $0,20 | - | | GLM 4.7 | $0,60 | $2.20 | $0,10 | - | | GLM 4.6 | $0,60 | $2.20 | $0,10 | - | -| Kimi K2.5 Free | Gratis | Gratis | Gratis | - | | Kimi K2.5 | $0,60 | $3.00 | $0,08 | - | | Kimi K2 Thinking | $0,40 | $2.50 | - | - | | Kimi K2 | $0,40 | $2.50 | - | - | | Qwen3 Coder 480B | $0,45 | $1,50 | - | - | +| Claude Opus 4.6 (≤ 200.000 tokens) | $5.00 | $25.00 | $0,50 | $6.25 | +| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37,50 | $1.00 | $12,50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0,50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1,50 | $18,75 | +| Claude Sonnet 4.6 (≤ 200.000 tokens) | $3.00 | $15.00 | $0,30 | $3,75 | +| Claude Sonnet 4.6 (> 200.000 tokens) | $6.00 | $22,50 | $0,60 | $7.50 | | Claude Sonnet 4.5 (≤ 200.000 tokens) | $3.00 | $15.00 | $0,30 | $3,75 | | Claude Sonnet 4.5 (> 200.000 tokens) | $6.00 | $22,50 | $0,60 | $7.50 | | Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0,30 | $3,75 | | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22,50 | $0,60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0,10 | $1,25 | | Claude Haiku 3.5 | $0,80 | $4.00 | $0,08 | $1.00 | -| Claude Opus 4.6 (≤ 200.000 tokens) | $5.00 | $25.00 | $0,50 | $6.25 | -| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37,50 | $1.00 | $12,50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0,50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1,50 | $18,75 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0,20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4.00 | $18.00 | $0,40 | - | | Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0,20 | - | | Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0,40 | - | | Gemini 3 Flash | $0,50 | $3.00 | $0,05 | - | +| GPT 5.3 Codex | $1,75 | $14.00 | $0,175 | - | | GPT 5.2 | $1,75 | $14.00 | $0,175 | - | | GPT 5.2 Codex | $1,75 | $14.00 | $0,175 | - | | GPT 5.1 | $1.07 | $8,50 | $0,107 | - | @@ -156,9 +164,7 @@ Las tarifas de las tarjetas de crédito se trasladan al costo (4,4% + 0,30 dóla Los modelos gratuitos: -- GLM 4.7 Free está disponible en OpenCode por tiempo limitado. El equipo está aprovechando este tiempo para recopilar comentarios y mejorar el modelo. -- Kimi K2.5 Free está disponible en OpenCode por tiempo limitado. El equipo está aprovechando este tiempo para recopilar comentarios y mejorar el modelo. -- MiniMax M2.1 Free está disponible en OpenCode por tiempo limitado. El equipo está aprovechando este tiempo para recopilar comentarios y mejorar el modelo. +- MiniMax M2.5 Free está disponible en OpenCode por tiempo limitado. El equipo está aprovechando este tiempo para recopilar comentarios y mejorar el modelo. - Big Pickle es un modelo sigiloso gratuito en OpenCode por tiempo limitado. El equipo está aprovechando este tiempo para recopilar comentarios y mejorar el modelo. Contáctenos si tiene alguna pregunta. @@ -189,9 +195,7 @@ cobrarle más de $20 si su saldo es inferior a $5. Todos nuestros modelos están alojados en los EE. UU. Nuestros proveedores siguen una política de retención cero y no utilizan sus datos para la capacitación de modelos, con las siguientes excepciones: - Big Pickle: Durante su periodo gratuito, los datos recopilados podrán utilizarse para mejorar el modelo. -- GLM 4.7 Gratis: Durante su periodo gratuito, los datos recopilados podrán utilizarse para mejorar el modelo. -- Kimi K2.5 Free: Durante su periodo gratuito, los datos recopilados podrán utilizarse para mejorar el modelo. -- MiniMax M2.1 Free: Durante su período gratuito, los datos recopilados podrán utilizarse para mejorar el modelo. +- MiniMax M2.5 Free: Durante su período gratuito, los datos recopilados podrán utilizarse para mejorar el modelo. - API de OpenAI: las solicitudes se conservan durante 30 días de acuerdo con las [Políticas de datos de OpenAI](https://platform.openai.com/docs/guides/your-data). - API de Anthropic: las solicitudes se conservan durante 30 días de acuerdo con las [Políticas de datos de Anthropic](https://docs.anthropic.com/en/docs/claude-code/data-usage). diff --git a/packages/web/src/content/docs/fr/cli.mdx b/packages/web/src/content/docs/fr/cli.mdx index 8773d941f3..92a473d34b 100644 --- a/packages/web/src/content/docs/fr/cli.mdx +++ b/packages/web/src/content/docs/fr/cli.mdx @@ -558,6 +558,7 @@ OpenCode peut être configuré à l'aide de variables d'environnement. | `OPENCODE_AUTO_SHARE` | booléen | Partager automatiquement des sessions | | `OPENCODE_GIT_BASH_PATH` | chaîne | Chemin vers l'exécutable Git Bash sur Windows | | `OPENCODE_CONFIG` | chaîne | Chemin d'accès au fichier de configuration | +| `OPENCODE_TUI_CONFIG` | chaîne | Chemin d'accès au fichier de configuration TUI | | `OPENCODE_CONFIG_DIR` | chaîne | Chemin d'accès au répertoire de configuration | | `OPENCODE_CONFIG_CONTENT` | chaîne | Contenu de configuration JSON en ligne | | `OPENCODE_DISABLE_AUTOUPDATE` | booléen | Désactiver les vérifications automatiques des mises à jour | diff --git a/packages/web/src/content/docs/fr/config.mdx b/packages/web/src/content/docs/fr/config.mdx index 8c0d15e183..c576fe2da1 100644 --- a/packages/web/src/content/docs/fr/config.mdx +++ b/packages/web/src/content/docs/fr/config.mdx @@ -14,10 +14,11 @@ OpenCode prend en charge les formats **JSON** et **JSONC** (JSON avec commentair ```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", - // Theme configuration - "theme": "opencode", "model": "anthropic/claude-sonnet-4-5", "autoupdate": true, + "server": { + "port": 4096, + }, } ``` @@ -34,7 +35,7 @@ Les fichiers de configuration sont **fusionnés**, pas remplacés. Les fichiers de configuration sont fusionnés et non remplacés. Les paramètres des emplacements de configuration suivants sont combinés. Les configurations ultérieures remplacent les précédentes uniquement en cas de clés en conflit. Les paramètres non conflictuels de toutes les configurations sont conservés. -Par exemple, si votre configuration globale définit `theme: "opencode"` et `autoupdate: true` et que la configuration de votre projet définit `model: "anthropic/claude-sonnet-4-5"`, la configuration finale inclura les trois paramètres. +Par exemple, si votre configuration globale définit `autoupdate: true` et que la configuration de votre projet définit `model: "anthropic/claude-sonnet-4-5"`, la configuration finale inclura les deux paramètres. --- @@ -95,7 +96,9 @@ Vous pouvez activer des serveurs spécifiques dans votre configuration locale : ### Globale -Placez votre configuration globale OpenCode dans `~/.config/opencode/opencode.json`. Utilisez la configuration globale pour les préférences de l'utilisateur telles que les thèmes, les fournisseurs ou les raccourcis clavier. +Placez votre configuration globale OpenCode dans `~/.config/opencode/opencode.json`. Utilisez la configuration globale pour les préférences de l'utilisateur telles que les fournisseurs, les modèles et les autorisations. + +Pour les paramètres spécifiques à TUI, utilisez `~/.config/opencode/tui.json`. La configuration globale remplace les paramètres par défaut de l'organisation distante. @@ -105,6 +108,8 @@ La configuration globale remplace les paramètres par défaut de l'organisation Ajoutez `opencode.json` à la racine de votre projet. La configuration du projet a la priorité la plus élevée parmi les fichiers de configuration standard : elle remplace les configurations globales et distantes. +Pour les paramètres TUI spécifiques au projet, ajoutez `tui.json` à côté. + :::tip Placez la configuration spécifique au projet à la racine de votre projet. ::: @@ -145,34 +150,32 @@ Le répertoire personnalisé est chargé après les répertoires de configuratio Le fichier de configuration a un schéma défini dans [**`opencode.ai/config.json`**](https://opencode.ai/config.json). +La configuration TUI utilise [**`opencode.ai/tui.json`**](https://opencode.ai/tui.json). + Votre éditeur doit être capable de valider et de compléter automatiquement en fonction du schéma. --- ### TUI -Vous pouvez configurer les paramètres spécifiques à TUI via l'option `tui`. +Utilisez un fichier dédié `tui.json` (ou `tui.jsonc`) pour les paramètres spécifiques à TUI. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - }, - "diff_style": "auto" - } + "$schema": "https://opencode.ai/tui.json", + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` -Options disponibles : +Utilisez `OPENCODE_TUI_CONFIG` pour pointer vers un fichier de configuration TUI personnalisé. -- `scroll_acceleration.enabled` - Active l'accélération de défilement de style macOS. **A priorité sur `scroll_speed`.** -- `scroll_speed` - Multiplicateur de vitesse de défilement personnalisé (par défaut : `3`, minimum : `1`). Ignoré si `scroll_acceleration.enabled` est `true`. -- `diff_style` - Contrôle le rendu différentiel. `"auto"` s'adapte à la largeur du terminal, `"stacked"` affiche toujours une seule colonne. +Les anciennes clés `theme`, `keybinds` et `tui` dans `opencode.json` sont obsolètes et migrées automatiquement lorsque cela est possible. -[En savoir plus sur l'utilisation du TUI ici](/docs/tui). +[En savoir plus sur l'utilisation du TUI ici](/docs/tui#configure). --- @@ -298,12 +301,12 @@ Les jetons du porteur (`AWS_BEARER_TOKEN_BEDROCK` ou `/connect`) ont priorité s ### Thèmes -Vous pouvez configurer le thème que vous souhaitez utiliser dans votre configuration OpenCode via l'option `theme`. +Définissez votre thème d'interface utilisateur dans `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "theme": "" + "$schema": "https://opencode.ai/tui.json", + "theme": "tokyonight" } ``` @@ -403,11 +406,11 @@ Vous pouvez également définir des commandes à l'aide de fichiers markdown dan ### Raccourcis clavier -Vous pouvez personnaliser vos raccourcis clavier via l'option `keybinds`. +Personnalisez les raccourcis clavier dans `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": {} } ``` @@ -487,13 +490,15 @@ Vous pouvez contrôler le comportement de compactage du contexte via l'option `c "$schema": "https://opencode.ai/config.json", "compaction": { "auto": true, - "prune": true + "prune": true, + "reserved": 10000 } } ``` - `auto` - Compacte automatiquement la session lorsque le contexte est plein (par défaut : `true`). - `prune` - Supprimez les anciennes sorties de l'outil pour économiser des tokens (par défaut : `true`). +- `reserved` - Tampon de jetons pour le compactage. Laisse suffisamment de marge pour éviter le débordement lors du compactage. --- diff --git a/packages/web/src/content/docs/fr/go.mdx b/packages/web/src/content/docs/fr/go.mdx new file mode 100644 index 0000000000..fc2b6aa6c6 --- /dev/null +++ b/packages/web/src/content/docs/fr/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: Abonnement à bas coût pour les modèles de code ouverts. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go est un abonnement à bas coût de **10 $/mois** qui vous donne un accès fiable aux modèles de code ouverts populaires. + +:::note +OpenCode Go est actuellement en bêta. +::: + +Go fonctionne comme tout autre fournisseur dans OpenCode. Vous vous abonnez à OpenCode Go et obtenez votre clé API. C'est **complètement optionnel** et vous n'avez pas besoin de l'utiliser pour utiliser OpenCode. + +Il est conçu principalement pour les utilisateurs internationaux, avec des modèles hébergés aux États-Unis, en UE et à Singapour pour un accès mondial stable. + +--- + +## Contexte + +Les modèles ouverts sont devenus vraiment bons. Ils atteignent maintenant des performances proches des modèles propriétaires pour les tâches de codage. Et parce que de nombreux fournisseurs peuvent les servir de manière compétitive, ils sont généralement beaucoup moins chers. + +Cependant, obtenir un accès fiable et à faible latence à ces modèles peut être difficile. Les fournisseurs varient en qualité et en disponibilité. + +:::tip +Nous avons testé un groupe sélectionné de modèles et de fournisseurs qui fonctionnent bien avec OpenCode. +::: + +Pour remédier à cela, nous avons fait plusieurs choses : + +1. Nous avons testé un groupe sélectionné de modèles ouverts et discuté avec leurs équipes de la meilleure façon de les exécuter. +2. Nous avons ensuite travaillé avec quelques fournisseurs pour nous assurer qu'ils étaient servis correctement. +3. Enfin, nous avons évalué la combinaison modèle/fournisseur et établi une liste que nous nous sentons à l'aise de recommander. + +OpenCode Go vous donne accès à ces modèles pour **10 $/mois**. + +--- + +## Comment ça marche + +OpenCode Go fonctionne comme tout autre fournisseur dans OpenCode. + +1. Vous vous connectez à **OpenCode Zen**, vous vous abonnez à Go et copiez votre clé API. +2. Vous exécutez la commande `/connect` dans la TUI, sélectionnez `OpenCode Go`, et collez votre clé API. +3. Exécutez `/models` dans la TUI pour voir la liste des modèles disponibles via Go. + +:::note +Un seul membre par espace de travail peut s'abonner à OpenCode Go. +::: + +La liste actuelle des modèles inclut : + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +La liste des modèles peut changer à mesure que nous testons et ajoutons de nouveaux modèles. + +--- + +## Limites d'utilisation + +OpenCode Go inclut les limites suivantes : + +- **Limite de 5 heures** — 12 $ d'utilisation +- **Limite hebdomadaire** — 30 $ d'utilisation +- **Limite mensuelle** — 60 $ d'utilisation + +Les limites sont définies en valeur monétaire. Cela signifie que votre nombre réel de requêtes dépend du modèle que vous utilisez. Les modèles moins chers comme MiniMax M2.5 permettent plus de requêtes, tandis que les modèles plus coûteux comme GLM-5 en permettent moins. + +Le tableau ci-dessous fournit une estimation du nombre de requêtes basée sur des modèles d'utilisation typiques de Go : + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| --------------------- | ----- | --------- | ------------ | +| requêtes par 5 heures | 1 150 | 1 850 | 30 000 | +| requêtes par semaine | 2 880 | 4 630 | 75 000 | +| requêtes par mois | 5 750 | 9 250 | 150 000 | + +Les estimations sont basées sur des modèles de requêtes moyens observés : + +- GLM-5 — 700 tokens d'entrée, 52 000 en cache, 150 de sortie par requête +- Kimi K2.5 — 870 tokens d'entrée, 55 000 en cache, 200 de sortie par requête +- MiniMax M2.5 — 300 tokens d'entrée, 55 000 en cache, 125 de sortie par requête + +Vous pouvez suivre votre utilisation actuelle dans la **console**. + +:::tip +Si vous atteignez la limite d'utilisation, vous pouvez continuer à utiliser les modèles gratuits. +::: + +Les limites d'utilisation peuvent changer à mesure que nous apprenons des premiers usages et retours. + +--- + +### Tarification + +OpenCode Go est un plan d'abonnement à **10 $/mois**. Ci-dessous se trouvent les prix **par 1M de tokens**. + +| Modèle | Entrée | Sortie | Lecture en cache | +| ------------ | ------ | ------ | ---------------- | +| GLM-5 | 1,00 $ | 3,20 $ | 0,20 $ | +| Kimi K2.5 | 0,60 $ | 3,00 $ | 0,10 $ | +| MiniMax M2.5 | 0,30 $ | 1,20 $ | 0,03 $ | + +--- + +### Utilisation au-delà des limites + +Si vous avez aussi des crédits sur votre solde Zen, vous pouvez activer l'option **Use balance** dans la console. Lorsqu'elle est activée, Go basculera sur votre solde Zen après que vous ayez atteint vos limites d'utilisation au lieu de bloquer les requêtes. + +--- + +## Endpoints + +Vous pouvez également accéder aux modèles Go via les endpoints API suivants. + +| Modèle | ID du modèle | Endpoint | Package AI SDK | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +L'[ID du modèle](/docs/config/#models) dans votre configuration OpenCode utilise le format `opencode-go/`. Par exemple, pour Kimi K2.5, vous utiliseriez `opencode-go/kimi-k2.5` dans votre configuration. + +--- + +## Confidentialité + +Le plan est conçu principalement pour les utilisateurs internationaux, avec des modèles hébergés aux États-Unis, en UE et à Singapour pour un accès mondial stable. + +Contactez-nous si vous avez des questions. + +--- + +## Objectifs + +Nous avons créé OpenCode Go pour : + +1. Rendre le codage par IA **accessible** à plus de personnes avec un abonnement à bas coût. +2. Fournir un accès **fiable** aux meilleurs modèles de code ouverts. +3. Sélectionner des modèles qui sont **testés et évalués** pour l'utilisation d'agents de codage. +4. N'avoir **aucun verrouillage** en vous permettant d'utiliser tout autre fournisseur avec OpenCode également. diff --git a/packages/web/src/content/docs/fr/lsp.mdx b/packages/web/src/content/docs/fr/lsp.mdx index cf2dfb6180..8a83370da0 100644 --- a/packages/web/src/content/docs/fr/lsp.mdx +++ b/packages/web/src/content/docs/fr/lsp.mdx @@ -27,6 +27,7 @@ OpenCode est livré avec plusieurs serveurs LSP intégrés pour les langages pop | gopls | .go | Commande `go` disponible | | hls | .hs, .lhs | Commande `haskell-language-server-wrapper` disponible | | jdtls | .java | `Java SDK (version 21+)` installé | +| julials | .jl | `julia` et `LanguageServer.jl` installés | | kotlin-ls | .kt, .kts | Installation automatique pour les projets Kotlin | | lua-ls | .lua | Installation automatique pour les projets Lua | | nixd | .nix | Commande `nixd` disponible | diff --git a/packages/web/src/content/docs/fr/mcp-servers.mdx b/packages/web/src/content/docs/fr/mcp-servers.mdx index e1d1f24e7c..5d01286879 100644 --- a/packages/web/src/content/docs/fr/mcp-servers.mdx +++ b/packages/web/src/content/docs/fr/mcp-servers.mdx @@ -375,9 +375,9 @@ Si vous disposez d'un grand nombre de serveurs MCP, vous souhaiterez peut-être --- -#### Patterns glob +#### Modèles globaux -Le pattern glob utilise des modèles de globbing regex simples : +Le modèle glob utilise des modèles de globbing regex simples : - `*` correspond à zéro ou plusieurs caractères (par exemple, `"my-mcp*"` correspond à `my-mcp_search`, `my-mcp_list`, etc.) - `?` correspond exactement à un caractère @@ -509,473 +509,3 @@ Alternativement, vous pouvez ajouter quelque chose comme ceci à votre [AGENTS.m ```md title="AGENTS.md" If you are unsure how to do something, use `gh_grep` to search code examples from GitHub. ``` - -Vous pouvez également désactiver un serveur en définissant `enabled` sur `false`. Ceci est utile si vous souhaitez désactiver temporairement un serveur sans le supprimer de votre configuration. - ---- - -### Remplacement des valeurs par défaut distantes - -Les organisations peuvent fournir des serveurs MCP par défaut via leur point de terminaison `.well-known/opencode`. Ces serveurs peuvent être désactivés par défaut, permettant aux utilisateurs de choisir ceux dont ils ont besoin. - -Pour activer un serveur spécifique à partir de la configuration distante de votre organisation, ajoutez-le à votre configuration locale avec `enabled: true` : - -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "jira": { - "type": "remote", - "url": "https://jira.example.com/mcp", - "enabled": true - } - } -} -``` - -Vos valeurs de configuration locales remplacent les valeurs par défaut distantes. Voir [config precedence](/docs/config#precedence-order) pour plus de détails. - ---- - -## Local - -Ajoutez des serveurs MCP locaux en utilisant `type` à `"local"` dans l'objet MCP. - -```jsonc title="opencode.jsonc" {15} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-local-mcp-server": { - "type": "local", - // Or ["bun", "x", "my-mcp-command"] - "command": ["npx", "-y", "my-mcp-command"], - "enabled": true, - "environment": { - "MY_ENV_VAR": "my_env_var_value", - }, - }, - }, -} -``` - -La commande indique comment le serveur MCP local est démarré. Vous pouvez également transmettre une liste de variables d’environnement. - -Par exemple, voici comment ajouter le serveur de test [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) MCP. - -```jsonc title="opencode.jsonc" -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "mcp_everything": { - "type": "local", - "command": ["npx", "-y", "@modelcontextprotocol/server-everything"], - }, - }, -} -``` - -Et pour l'utiliser, je peux ajouter `use the mcp_everything tool` à mes invites. - -```txt "mcp_everything" -use the mcp_everything tool to add the number 3 and 4 -``` - ---- - -#### Options - -Voici toutes les options pour configurer un serveur MCP local. - -| Options | Tapez | Obligatoire | Descriptif | -| ------------- | ------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------- | -| `type` | Chaîne | Oui | Le type de connexion au serveur MCP doit être `"local"`. | -| `command` | Tableau | Oui | Commande et arguments pour exécuter le serveur MCP. | -| `environment` | Objet | | Variables d'environnement à définir lors de l'exécution du serveur. | -| `enabled` | Booléen | | Activez ou désactivez le serveur MCP au démarrage. | -| `timeout` | Numéro | | Délai d'expiration en ms pour la récupération des outils depuis le serveur MCP. La valeur par défaut est 5 000 (5 secondes). | - ---- - -## Remote - -Ajoutez des serveurs MCP distants en définissant `type` sur `"remote"`. - -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-remote-mcp": { - "type": "remote", - "url": "https://my-mcp-server.com", - "enabled": true, - "headers": { - "Authorization": "Bearer MY_API_KEY" - } - } - } -} -``` - -Le champ `url` est l'URL du serveur MCP distant et l'option `headers` vous permet de transmettre des en-têtes. - ---- - -#### Options - -| Options | Tapez | Obligatoire | Descriptif | -| --------- | ------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------- | -| `type` | Chaîne | Oui | Le type de connexion au serveur MCP doit être `"remote"`. | -| `url` | Chaîne | Oui | URL du serveur MCP distant. | -| `enabled` | Booléen | | Activez ou désactivez le serveur MCP au démarrage. | -| `headers` | Objet | | En-têtes à envoyer avec la demande. | -| `oauth` | Objet | | Configuration de l'authentification OAuth. Voir la section [OAuth](#oauth) ci-dessous. | -| `timeout` | Numéro | | Délai d'expiration en ms pour la récupération des outils depuis le serveur MCP. La valeur par défaut est 5 000 (5 secondes). | - ---- - -## OAuth - -OpenCode gère automatiquement l'authentification OAuth pour les serveurs MCP distants. Lorsqu'un serveur nécessite une authentification, OpenCode : - -1. Détectez la réponse 401 et lancez le flux OAuth -2. Utilisez **Enregistrement client dynamique (RFC 7591)** s'il est pris en charge par le serveur. -3. Stockez les jetons en toute sécurité pour les demandes futures - ---- - -### Automatique - -Pour la plupart des serveurs MCP compatibles OAuth, aucune configuration particulière n'est nécessaire. Configurez simplement le serveur distant : - -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-oauth-server": { - "type": "remote", - "url": "https://mcp.example.com/mcp" - } - } -} -``` - -Si le serveur nécessite une authentification, OpenCode vous demandera de vous authentifier lorsque vous essayez de l'utiliser pour la première fois. Sinon, vous pouvez [déclencher manuellement le flux](#authenticating) avec `opencode mcp auth `. - ---- - -### Pré-inscrit - -Si vous disposez des informations d'identification client du fournisseur de serveur MCP, vous pouvez les configurer : - -```json title="opencode.json" {7-11} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-oauth-server": { - "type": "remote", - "url": "https://mcp.example.com/mcp", - "oauth": { - "clientId": "{env:MY_MCP_CLIENT_ID}", - "clientSecret": "{env:MY_MCP_CLIENT_SECRET}", - "scope": "tools:read tools:execute" - } - } - } -} -``` - ---- - -### Authentification - -Vous pouvez déclencher manuellement l'authentification ou gérer les informations d'identification. - -Authentifiez-vous auprès d'un serveur MCP spécifique : - -```bash -opencode mcp auth my-oauth-server -``` - -Répertoriez tous les serveurs MCP et leur statut d'authentification : - -```bash -opencode mcp list -``` - -Supprimez les informations d'identification stockées : - -```bash -opencode mcp logout my-oauth-server -``` - -La commande `mcp auth` ouvrira votre navigateur pour autorisation. Après votre autorisation, OpenCode stockera les jetons en toute sécurité dans `~/.local/share/opencode/mcp-auth.json`. - ---- - -#### Désactivation de OAuth - -Si vous souhaitez désactiver le OAuth automatique pour un serveur (par exemple, pour les serveurs qui utilisent les clés API à la place), définissez `oauth` sur `false` : - -```json title="opencode.json" {7} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-api-key-server": { - "type": "remote", - "url": "https://mcp.example.com/mcp", - "oauth": false, - "headers": { - "Authorization": "Bearer {env:MY_API_KEY}" - } - } - } -} -``` - ---- - -#### Options OAuth - -| Options | Tapez | Descriptif | -| -------------- | ------------- | ---------------------------------------------------------------------------------------- | -| `oauth` | Objet \| faux | Objet de configuration OAuth, ou `false` pour désactiver la détection automatique OAuth. | -| `clientId` | Chaîne | ID client OAuth. S’il n’est pas fourni, l’enregistrement dynamique du client sera tenté. | -| `clientSecret` | Chaîne | OAuth secret client, si requis par le serveur d'autorisation. | -| `scope` | Chaîne | OAuth scopes à demander lors de l'autorisation. | - -#### Débogage - -Si un serveur MCP distant ne parvient pas à s'authentifier, vous pouvez diagnostiquer les problèmes avec : - -```bash -# View auth status for all OAuth-capable servers -opencode mcp auth list - -# Debug connection and OAuth flow for a specific server -opencode mcp debug my-oauth-server -``` - -La commande `mcp debug` affiche l'état d'authentification actuel, teste la connectivité HTTP et tente le flux de découverte OAuth. - ---- - -## Gérer - -Vos MCP sont disponibles sous forme d'outils dans OpenCode, aux côtés des outils intégrés. Vous pouvez donc les gérer via la configuration OpenCode comme n'importe quel autre outil. - ---- - -### Global - -Cela signifie que vous pouvez les activer ou les désactiver globalement. - -```json title="opencode.json" {14} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-mcp-foo": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-foo"] - }, - "my-mcp-bar": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-bar"] - } - }, - "tools": { - "my-mcp-foo": false - } -} -``` - -Nous pouvons également utiliser un modèle global pour désactiver tous les MCP correspondants. - -```json title="opencode.json" {14} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-mcp-foo": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-foo"] - }, - "my-mcp-bar": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-bar"] - } - }, - "tools": { - "my-mcp*": false - } -} -``` - -Ici, nous utilisons le modèle global `my-mcp*` pour désactiver tous les MCP. - ---- - -### Par agent - -Si vous disposez d'un grand nombre de serveurs MCP, vous souhaiterez peut-être les activer uniquement par agent et les désactiver globalement. Pour ce faire : - -1. Désactivez-le en tant qu'outil à l'échelle mondiale. -2. Dans votre [agent config](/docs/agents#tools), activez le serveur MCP en tant qu'outil. - -```json title="opencode.json" {11, 14-18} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-mcp": { - "type": "local", - "command": ["bun", "x", "my-mcp-command"], - "enabled": true - } - }, - "tools": { - "my-mcp*": false - }, - "agent": { - "my-agent": { - "tools": { - "my-mcp*": true - } - } - } -} -``` - ---- - -#### Modèles globaux - -Le modèle glob utilise des modèles de globbing regex simples : - -- `*` correspond à zéro ou plusieurs caractères (par exemple, `"my-mcp*"` correspond à `my-mcp_search`, `my-mcp_list`, etc.) -- `?` correspond exactement à un caractère -- Tous les autres caractères correspondent littéralement - -:::note -Les outils serveur MCP sont enregistrés avec le nom du serveur comme préfixe, donc pour désactiver tous les outils d'un serveur, utilisez simplement : - -``` -"mymcpservername_*": false -``` - -::: - ---- - -## Exemples - -Vous trouverez ci-dessous des exemples de serveurs MCP courants. Vous pouvez soumettre un PR si vous souhaitez documenter d'autres serveurs. - ---- - -### Sentry - -Ajoutez le [serveur Sentry MCP](https://mcp.sentry.dev) pour interagir avec vos projets et problèmes Sentry. - -```json title="opencode.json" {4-8} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "sentry": { - "type": "remote", - "url": "https://mcp.sentry.dev/mcp", - "oauth": {} - } - } -} -``` - -Après avoir ajouté la configuration, authentifiez-vous auprès de Sentry : - -```bash -opencode mcp auth sentry -``` - -Cela ouvrira une fenêtre de navigateur pour terminer le flux OAuth et connecter OpenCode à votre compte Sentry. - -Une fois authentifié, vous pouvez utiliser les outils Sentry dans vos invites pour interroger les problèmes, les projets et les données d'erreur. - -```txt "use sentry" -Show me the latest unresolved issues in my project. use sentry -``` - ---- - -### Contexte7 - -Ajoutez le [Context7 MCP server](https://github.com/upstash/context7) pour effectuer une recherche dans les documents. - -```json title="opencode.json" {4-7} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "context7": { - "type": "remote", - "url": "https://mcp.context7.com/mcp" - } - } -} -``` - -Si vous avez créé un compte gratuit, vous pouvez utiliser votre clé API et obtenir des limites de débit plus élevées. - -```json title="opencode.json" {7-9} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "context7": { - "type": "remote", - "url": "https://mcp.context7.com/mcp", - "headers": { - "CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}" - } - } - } -} -``` - -Ici, nous supposons que la variable d'environnement `CONTEXT7_API_KEY` est définie. - -Ajoutez `use context7` à vos invites pour utiliser le serveur Context7 MCP. - -```txt "use context7" -Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 -``` - -Alternativement, vous pouvez ajouter quelque chose comme ceci à votre [AGENTS.md](/docs/rules/). - -```md title="AGENTS.md" -When you need to search docs, use `context7` tools. -``` - ---- - -### Grep by Vercel - -Ajoutez le serveur [Grep by Vercel](https://grep.app) MCP pour rechercher des extraits de code sur GitHub. - -```json title="opencode.json" {4-7} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "gh_grep": { - "type": "remote", - "url": "https://mcp.grep.app" - } - } -} -``` - -Puisque nous avons nommé notre serveur MCP `gh_grep`, vous pouvez ajouter `use the gh_grep tool` à vos invites pour que l'agent l'utilise. - -```txt "use the gh_grep tool" -What's the right way to set a custom domain in an SST Astro component? use the gh_grep tool -``` - -Alternativement, vous pouvez ajouter quelque chose comme ceci à votre [AGENTS.md](/docs/rules/). - -```md title="AGENTS.md" -If you are unsure how to do something, use `gh_grep` to search code examples from GitHub. -``` diff --git a/packages/web/src/content/docs/fr/providers.mdx b/packages/web/src/content/docs/fr/providers.mdx index b65e9c00a1..36e1ed2d2b 100644 --- a/packages/web/src/content/docs/fr/providers.mdx +++ b/packages/web/src/content/docs/fr/providers.mdx @@ -84,6 +84,38 @@ Il fonctionne comme n’importe quel autre fournisseur dans OpenCode et son util --- +## OpenCode Go + +OpenCode Go est un plan d'abonnement à faible coût qui offre un accès fiable aux modèles de codage ouverts populaires fournis par l'équipe OpenCode qui ont été +testé et vérifié pour fonctionner correctement avec OpenCode. + +1. Exécutez la commande `/connect` dans le TUI, sélectionnez `OpenCode Go` et rendez-vous sur [opencode.ai/auth](https://opencode.ai/zen). + + ```txt + /connect + ``` + +2. Connectez-vous, ajoutez vos informations de facturation et copiez votre clé API. + +3. Collez votre clé API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez `/models` dans le TUI pour voir la liste des modèles que nous recommandons. + + ```txt + /models + ``` + +Il fonctionne comme n’importe quel autre fournisseur dans OpenCode et son utilisation est totalement facultative. + +--- + ## Annuaire Examinons certains fournisseurs en détail. Si vous souhaitez ajouter un fournisseur au @@ -1487,6 +1519,39 @@ Ou ajoutez-le à votre profil bash : --- +### STACKIT + +STACKIT AI Model Serving fournit un environnement d'hébergement souverain entièrement géré pour les modèles d'IA, se concentrant sur les LLM comme Llama, Mistral et Qwen, avec une souveraineté maximale des données sur l'infrastructure européenne. + +1. Rendez-vous sur le [portail STACKIT](https://portal.stackit.cloud), accédez à **AI Model Serving** et créez un jeton d'authentification pour votre projet. + + :::tip + Vous avez besoin d'un compte client STACKIT, d'un compte utilisateur et d'un projet avant de créer des jetons d'authentification. + ::: + +2. Exécutez la commande `/connect` et recherchez **STACKIT**. + + ```txt + /connect + ``` + +3. Entrez votre jeton d'authentification STACKIT AI Model Serving. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Exécutez la commande `/models` pour sélectionner parmi les modèles disponibles tels que _Qwen3-VL 235B_ ou _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + ### OVHcloud AI Endpoints 1. Rendez-vous sur le [Panneau OVHcloud](https://ovh.com/manager). Accédez à la section `Public Cloud`, `AI & Machine Learning` > `AI Endpoints` et dans l'onglet `API Keys`, cliquez sur **Créer une nouvelle clé API**. diff --git a/packages/web/src/content/docs/fr/sdk.mdx b/packages/web/src/content/docs/fr/sdk.mdx index 0e67aebd00..ee3a2dc49c 100644 --- a/packages/web/src/content/docs/fr/sdk.mdx +++ b/packages/web/src/content/docs/fr/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## Sortie structurée + +Vous pouvez demander une sortie JSON structurée au modèle en spécifiant un `format` avec un schéma JSON. Le modèle utilisera un outil `StructuredOutput` pour renvoyer un JSON validé correspondant à votre schéma. + +### Utilisation de base + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Access the structured output +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### Types de format de sortie + +| Type | Description | +| ------------- | ----------------------------------------------------------------- | +| `text` | Par défaut. Réponse textuelle standard (pas de sortie structurée) | +| `json_schema` | Renvoie un JSON validé correspondant au schéma fourni | + +### Format de schéma JSON + +Lors de l'utilisation de `type: 'json_schema'`, fournissez : + +| Champ | Type | Description | +| ------------ | --------------- | --------------------------------------------------------------- | +| `type` | `'json_schema'` | Requis. Spécifie le mode de schéma JSON | +| `schema` | `object` | Requis. Objet JSON Schema définissant la structure de sortie | +| `retryCount` | `number` | Facultatif. Nombre de tentatives de validation (par défaut : 2) | + +### Gestion des erreurs + +Si le modèle ne parvient pas à produire une sortie structurée valide après toutes les tentatives, la réponse inclura une `StructuredOutputError` : + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### Bonnes pratiques + +1. **Fournissez des descriptions claires** dans les propriétés de votre schéma pour aider le modèle à comprendre quelles données extraire +2. **Utilisez `required`** pour spécifier quels champs doivent être présents +3. **Gardez les schémas ciblés** - les schémas imbriqués complexes peuvent être plus difficiles à remplir correctement pour le modèle +4. **Définissez un `retryCount` approprié** - augmentez-le pour les schémas complexes, diminuez-le pour les simples + +--- + ## APIs Le SDK expose toutes les API du serveur via un client de type sécurisé. @@ -226,27 +298,27 @@ const { providers, default: defaults } = await client.config.providers() ### Séances -| Méthode | Descriptif | Remarques | -| ---------------------------------------------------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | Liste des séances | Renvoie Session[] | -| `session.get({ path })` | Obtenir une session | Renvoie Session | -| `session.children({ path })` | Liste des sessions enfants | Renvoie Session[] | -| `session.create({ body })` | Créer une séance | Renvoie Session | -| `session.delete({ path })` | Supprimer la séance | Renvoie `boolean` | -| `session.update({ path, body })` | Mettre à jour les propriétés de la session | Renvoie Session | -| `session.init({ path, body })` | Analysez l'application et créez `AGENTS.md` | Renvoie `boolean` | -| `session.abort({ path })` | Abandonner une session en cours | Renvoie `boolean` | -| `session.share({ path })` | Séance de partage | Renvoie Session | -| `session.unshare({ path })` | Annuler le partage de la session | Renvoie Session | -| `session.summarize({ path, body })` | Résumer la séance | Renvoie `boolean` | -| `session.messages({ path })` | Liste des messages dans une session | Renvoie `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ path })` | Obtenir les détails du message | Renvoie `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | Envoyer un message d'invite | `body.noReply: true` renvoie UserMessage (contexte uniquement). La valeur par défaut renvoie AssistantMessage avec réponse IA | -| `session.command({ path, body })` | Envoyer la commande à la session | Renvoie `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | Exécuter une commande shell | Renvoie AssistantMessage | -| `session.revert({ path, body })` | Rétablir un message | Renvoie Session | -| `session.unrevert({ path })` | Restaurer les messages annulés | Renvoie Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | Répondre à une demande d'autorisation | Renvoie `boolean` | +| Méthode | Descriptif | Remarques | +| ---------------------------------------------------------- | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | Liste des séances | Renvoie Session[] | +| `session.get({ path })` | Obtenir une session | Renvoie Session | +| `session.children({ path })` | Liste des sessions enfants | Renvoie Session[] | +| `session.create({ body })` | Créer une séance | Renvoie Session | +| `session.delete({ path })` | Supprimer la séance | Renvoie `boolean` | +| `session.update({ path, body })` | Mettre à jour les propriétés de la session | Renvoie Session | +| `session.init({ path, body })` | Analysez l'application et créez `AGENTS.md` | Renvoie `boolean` | +| `session.abort({ path })` | Abandonner une session en cours | Renvoie `boolean` | +| `session.share({ path })` | Séance de partage | Renvoie Session | +| `session.unshare({ path })` | Annuler le partage de la session | Renvoie Session | +| `session.summarize({ path, body })` | Résumer la séance | Renvoie `boolean` | +| `session.messages({ path })` | Liste des messages dans une session | Renvoie `{ info: `Message`, parts: `Part[]`}[]` | +| `session.message({ path })` | Obtenir les détails du message | Renvoie `{ info: `Message`, parts: `Part[]`}` | +| `session.prompt({ path, body })` | Envoyer un message d'invite | `body.noReply: true` renvoie UserMessage (contexte uniquement). La valeur par défaut renvoie AssistantMessage avec réponse IA. Prend en charge `body.outputFormat` pour [sortie structurée](#structured-output) | +| `session.command({ path, body })` | Envoyer la commande à la session | Renvoie `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `session.shell({ path, body })` | Exécuter une commande shell | Renvoie AssistantMessage | +| `session.revert({ path, body })` | Rétablir un message | Renvoie Session | +| `session.unrevert({ path })` | Restaurer les messages annulés | Renvoie Session | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | Répondre à une demande d'autorisation | Renvoie `boolean` | --- diff --git a/packages/web/src/content/docs/fr/themes.mdx b/packages/web/src/content/docs/fr/themes.mdx index d17f2169c7..696e56d59c 100644 --- a/packages/web/src/content/docs/fr/themes.mdx +++ b/packages/web/src/content/docs/fr/themes.mdx @@ -61,11 +61,11 @@ Le thème système est destiné aux utilisateurs qui : ## Utiliser un thème -Vous pouvez sélectionner un thème en affichant la sélection de thème avec la commande `/theme`. Ou vous pouvez le spécifier dans votre [config](/docs/config). +Vous pouvez sélectionner un thème en affichant la sélection de thème avec la commande `/theme`. Ou vous pouvez le spécifier dans `tui.json`. -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` diff --git a/packages/web/src/content/docs/fr/tui.mdx b/packages/web/src/content/docs/fr/tui.mdx index f9078508dd..8129eb2012 100644 --- a/packages/web/src/content/docs/fr/tui.mdx +++ b/packages/web/src/content/docs/fr/tui.mdx @@ -355,24 +355,34 @@ Certains éditeurs ont besoin d'arguments de ligne de commande pour s'exécuter ## Configurer -Vous pouvez personnaliser le comportement de TUI via votre fichier de configuration OpenCode. +Vous pouvez personnaliser le comportement de TUI via `tui.json` (ou `tui.jsonc`). -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +Ceci est séparé de `opencode.json`, qui configure le comportement du serveur/d'exécution. + ### Options -- `scroll_acceleration` - Activez l'accélération de défilement de style macOS pour un défilement fluide et naturel. Lorsqu'elle est activée, la vitesse de défilement augmente avec les gestes de défilement rapides et reste précise pour les mouvements plus lents. **Ce paramètre est prioritaire sur `scroll_speed` et le remplace lorsqu'il est activé.** -- `scroll_speed` - Contrôle la vitesse de défilement du TUI lors de l'utilisation des commandes de défilement (minimum : `1`). La valeur par défaut est `3`. **Remarque : Ceci est ignoré si `scroll_acceleration.enabled` est défini sur `true`.** +- `theme` - Définit votre thème d'interface utilisateur. [En savoir plus](/docs/themes). +- `keybinds` - Personnalise les raccourcis clavier. [En savoir plus](/docs/keybinds). +- `scroll_acceleration.enabled` - Activez l'accélération de défilement de style macOS pour un défilement fluide et naturel. Lorsqu'elle est activée, la vitesse de défilement augmente avec les gestes de défilement rapides et reste précise pour les mouvements plus lents. **Ce paramètre est prioritaire sur `scroll_speed` et le remplace lorsqu'il est activé.** +- `scroll_speed` - Contrôle la vitesse de défilement du TUI lors de l'utilisation des commandes de défilement (minimum : `0.001`, prend en charge les valeurs décimales). La valeur par défaut est `3`. **Remarque : Ceci est ignoré si `scroll_acceleration.enabled` est défini sur `true`.** +- `diff_style` - Contrôle le rendu différentiel. `"auto"` s'adapte à la largeur du terminal, `"stacked"` affiche toujours une seule colonne. + +Utilisez `OPENCODE_TUI_CONFIG` pour charger un chemin de configuration TUI personnalisé. --- diff --git a/packages/web/src/content/docs/fr/zen.mdx b/packages/web/src/content/docs/fr/zen.mdx index c69f2632f6..e40b1be77e 100644 --- a/packages/web/src/content/docs/fr/zen.mdx +++ b/packages/web/src/content/docs/fr/zen.mdx @@ -13,33 +13,25 @@ OpenCode Zen est une liste de modèles testés et vérifiés fournie par l'équi OpenCode Zen est actuellement en version bêta. ::: -Zen fonctionne comme n'importe quel autre fournisseur dans OpenCode. Vous vous connectez à OpenCode Zen et obtenez -votre clé API. C'est **complètement facultatif** et vous n'avez pas besoin de l'utiliser pour l'utiliser -OpenCode. +Zen fonctionne comme n'importe quel autre fournisseur dans OpenCode. Vous vous connectez à OpenCode Zen et obtenez votre clé API. C'est **complètement facultatif** et vous n'avez pas besoin de l'utiliser pour utiliser OpenCode. --- ## Arrière-plan -Il existe un grand nombre de modèles, mais seulement quelques-uns d'entre eux -ces modèles fonctionnent bien comme agents de codage. De plus, la plupart des fournisseurs sont -configuré très différemment; vous obtenez donc des performances et une qualité très différentes. +Il existe un grand nombre de modèles, mais seulement quelques-uns d'entre eux fonctionnent bien comme agents de codage. De plus, la plupart des fournisseurs sont configurés très différemment; vous obtenez donc des performances et une qualité très différentes. :::tip Nous avons testé un groupe sélectionné de modèles et de fournisseurs qui fonctionnent bien avec OpenCode. ::: -Donc, si vous utilisez un modèle via quelque chose comme OpenRouter, vous ne pourrez jamais être -assurez-vous que vous obtenez la meilleure version du modèle que vous souhaitez. +Donc, si vous utilisez un modèle via quelque chose comme OpenRouter, vous ne pourrez jamais être sûr que vous obtenez la meilleure version du modèle que vous souhaitez. -Pour résoudre ce problème, nous avons effectué plusieurs opérations : +Pour résoudre ce problème, nous avons effectué plusieurs opérations : -1. Nous avons testé un groupe sélectionné de modèles et discuté avec leurs équipes de la manière de - mieux vaut les exécuter. -2. Nous avons ensuite travaillé avec quelques prestataires pour nous assurer qu'ils étaient servis. - correctement. -3. Enfin, nous avons comparé la combinaison modèle/fournisseur et sommes arrivés - avec une liste que nous nous ferons un plaisir de recommander. +1. Nous avons testé un groupe sélectionné de modèles et discuté avec leurs équipes de la manière de mieux les exécuter. +2. Nous avons ensuite travaillé avec quelques prestataires pour nous assurer qu'ils étaient servis correctement. +3. Enfin, nous avons comparé la combinaison modèle/fournisseur et sommes arrivés avec une liste que nous nous ferons un plaisir de recommander. OpenCode Zen est une passerelle IA qui vous donne accès à ces modèles. @@ -49,8 +41,7 @@ OpenCode Zen est une passerelle IA qui vous donne accès à ces modèles. OpenCode Zen fonctionne comme n'importe quel autre fournisseur dans OpenCode. -1. Vous vous connectez à **OpenCode Zen**, ajoutez votre facturation - détails et copiez votre clé API. +1. Vous vous connectez à **OpenCode Zen**, ajoutez vos informations de facturation et copiez votre clé API. 2. Vous exécutez la commande `/connect` dans le TUI, sélectionnez OpenCode Zen et collez votre clé API. 3. Exécutez `/models` dans le TUI pour voir la liste des modèles que nous recommandons. @@ -64,6 +55,7 @@ Vous pouvez également accéder à nos modèles via les points de terminaison AP | Modèle | ID du modèle | Point de terminaison | Package SDK IA | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -73,36 +65,36 @@ Vous pouvez également accéder à nos modèles via les points de terminaison AP | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Big Pickle | big-pickle | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -Le [id du modèle](/docs/config/#models) dans votre configuration OpenCode -utilise le format `opencode/`. Par exemple, pour GPT 5.2 Codex, vous devez -utilisez `opencode/gpt-5.2-codex` dans votre configuration. +Le [id du modèle](/docs/config/#models) dans votre configuration OpenCode utilise le format `opencode/`. Par exemple, pour GPT 5.2 Codex, vous devez utilisez `opencode/gpt-5.2-codex` dans votre configuration. --- ### Modèles -Vous pouvez récupérer la liste complète des modèles disponibles et leurs métadonnées à partir de : +Vous pouvez récupérer la liste complète des modèles disponibles et leurs métadonnées à partir de : ``` https://opencode.ai/zen/v1/models @@ -117,29 +109,34 @@ Nous soutenons un modèle de paiement à l'utilisation. Vous trouverez ci-dessou | Modèle | Entrée | Sortie | Lecture en cache | Écriture en cache | | --------------------------------- | ------- | ------- | ---------------- | ----------------- | | Big Pickle | Gratuit | Gratuit | Gratuit | - | -| MiniMax M2.1 Free | Gratuit | Gratuit | Gratuit | - | +| MiniMax M2.5 Free | Gratuit | Gratuit | Gratuit | - | +| MiniMax M2.5 | 0,30 $ | 1,20 $ | 0,06 $ | - | | MiniMax M2.1 | 0,30 $ | 1,20 $ | 0,10 $ | - | -| GLM 4.7 Free | Gratuit | Gratuit | Gratuit | - | +| GLM 5 | 1,00 $ | 3,20 $ | 0,20 $ | - | | GLM 4.7 | 0,60 $ | 2,20 $ | 0,10 $ | - | | GLM 4.6 | 0,60 $ | 2,20 $ | 0,10 $ | - | -| Kimi K2.5 Free | Gratuit | Gratuit | Gratuit | - | | Kimi K2.5 | 0,60 $ | 3,00 $ | 0,08 $ | - | | Kimi K2 Thinking | 0,40 $ | 2,50 $ | - | - | | Kimi K2 | 0,40 $ | 2,50 $ | - | - | | Qwen3 Coder 480B | 0,45 $ | 1,50 $ | - | - | +| Claude Opus 4.6 (≤ 200K jetons) | 5,00 $ | 25,00 $ | 0,50 $ | 6,25 $ | +| Claude Opus 4.6 (> 200K jetons) | 10,00 $ | 37,50 $ | 1,00 $ | 12,50 $ | +| Claude Opus 4.5 | 5,00 $ | 25,00 $ | 0,50 $ | 6,25 $ | +| Claude Opus 4.1 | 15,00 $ | 75,00 $ | 1,50 $ | 18,75 $ | +| Claude Sonnet 4.6 (≤ 200K jetons) | 3,00 $ | 15,00 $ | 0,30 $ | 3,75 $ | +| Claude Sonnet 4.6 (> 200K jetons) | 6,00 $ | 22,50 $ | 0,60 $ | 7,50 $ | | Claude Sonnet 4.5 (≤ 200K jetons) | 3,00 $ | 15,00 $ | 0,30 $ | 3,75 $ | | Claude Sonnet 4.5 (> 200K jetons) | 6,00 $ | 22,50 $ | 0,60 $ | 7,50 $ | | Claude Sonnet 4 (≤ 200K jetons) | 3,00 $ | 15,00 $ | 0,30 $ | 3,75 $ | | Claude Sonnet 4 (> 200K jetons) | 6,00 $ | 22,50 $ | 0,60 $ | 7,50 $ | | Claude Haiku 4.5 | 1,00 $ | 5,00 $ | 0,10 $ | 1,25 $ | | Claude Haiku 3.5 | 0,80 $ | 4,00 $ | 0,08 $ | 1,00 $ | -| Claude Opus 4.6 (≤ 200K jetons) | 5,00 $ | 25,00 $ | 0,50 $ | 6,25 $ | -| Claude Opus 4.6 (> 200K jetons) | 10,00 $ | 37,50 $ | 1,00 $ | 12,50 $ | -| Claude Opus 4.5 | 5,00 $ | 25,00 $ | 0,50 $ | 6,25 $ | -| Claude Opus 4.1 | 15,00 $ | 75,00 $ | 1,50 $ | 18,75 $ | -| Gemini 3 Pro (≤ 200 000 jetons) | 2,00 $ | 12,00 $ | 0,20 $ | - | -| Gemini 3 Pro (> 200 000 jetons) | 4,00 $ | 18,00 $ | 0,40 $ | - | +| Gemini 3.1 Pro (≤ 200K jetons) | 2,00 $ | 12,00 $ | 0,20 $ | - | +| Gemini 3.1 Pro (> 200K jetons) | 4,00 $ | 18,00 $ | 0,40 $ | - | +| Gemini 3 Pro (≤ 200K jetons) | 2,00 $ | 12,00 $ | 0,20 $ | - | +| Gemini 3 Pro (> 200K jetons) | 4,00 $ | 18,00 $ | 0,40 $ | - | | Gemini 3 Flash | 0,50 $ | 3,00 $ | 0,05 $ | - | +| GPT 5.3 Codex | 1,75 $ | 14,00 $ | 0,175 $ | - | | GPT 5.2 | 1,75 $ | 14,00 $ | 0,175 $ | - | | GPT 5.2 Codex | 1,75 $ | 14,00 $ | 0,175 $ | - | | GPT 5.1 | 1,07 $ | 8,50 $ | 0,107 $ | - | @@ -158,9 +155,7 @@ Les frais de carte de crédit sont répercutés au prix coûtant (4,4 % + 0,30 $ Les modèles gratuits : -- GLM 4.7 Free est disponible sur OpenCode pour une durée limitée. L’équipe profite de ce temps pour recueillir des commentaires et améliorer le modèle. -- Kimi K2.5 Free est disponible sur OpenCode pour une durée limitée. L’équipe profite de ce temps pour recueillir des commentaires et améliorer le modèle. -- MiniMax M2.1 Free est disponible sur OpenCode pour une durée limitée. L’équipe profite de ce temps pour recueillir des commentaires et améliorer le modèle. +- MiniMax M2.5 Free est disponible sur OpenCode pour une durée limitée. L’équipe profite de ce temps pour recueillir des commentaires et améliorer le modèle. - Big Pickle est un modèle furtif gratuit sur OpenCode pour une durée limitée. L’équipe profite de ce temps pour recueillir des commentaires et améliorer le modèle. Contactez-nous si vous avez des questions. @@ -177,48 +172,41 @@ Vous pouvez modifier le montant du rechargement automatique. Vous pouvez égalem ### Limites mensuelles -Vous pouvez également définir une limite d'utilisation mensuelle pour l'ensemble de l'espace de travail et pour chaque -membre de votre équipe. +Vous pouvez également définir une limite d'utilisation mensuelle pour l'ensemble de l'espace de travail et pour chaque membre de votre équipe. -Par exemple, disons que vous définissez une limite d'utilisation mensuelle à 20 $, Zen n'utilisera pas -plus de 20 $ par mois. Mais si le rechargement automatique est activé, Zen pourrait finir par -vous facturant plus de 20 $ si votre solde descend en dessous de 5 $. +Par exemple, disons que vous définissez une limite d'utilisation mensuelle à 20 $, Zen n'utilisera pas plus de 20 $ par mois. Mais si le rechargement automatique est activé, Zen pourrait finir par vous facturant plus de 20 $ si votre solde descend en dessous de 5 $. --- ## Confidentialité -Tous nos modèles sont hébergés aux États-Unis. Nos fournisseurs suivent une politique de rétention zéro et n'utilisent pas vos données pour la formation de modèles, avec les exceptions suivantes : +Tous nos modèles sont hébergés aux États-Unis. Nos fournisseurs suivent une politique de rétention zéro et n'utilisent pas vos données pour la formation de modèles, avec les exceptions suivantes : - Big Pickle : Pendant sa période gratuite, les données collectées peuvent être utilisées pour améliorer le modèle. -- GLM 4.7 Gratuit : Pendant sa période gratuite, les données collectées peuvent être utilisées pour améliorer le modèle. -- Kimi K2.5 Gratuit : Pendant sa période gratuite, les données collectées peuvent être utilisées pour améliorer le modèle. -- MiniMax M2.1 Gratuit : Pendant sa période gratuite, les données collectées peuvent être utilisées pour améliorer le modèle. -- API OpenAI : les demandes sont conservées pendant 30 jours conformément aux politiques de données de [OpenAI](https://platform.openai.com/docs/guides/your-data). -- API Anthropic : les demandes sont conservées pendant 30 jours conformément aux [Politiques de données d'Anthropic](https://docs.anthropic.com/en/docs/claude-code/data-usage). +- MiniMax M2.5 Free : Pendant sa période gratuite, les données collectées peuvent être utilisées pour améliorer le modèle. +- API OpenAI : Les demandes sont conservées pendant 30 jours conformément aux politiques de données de [OpenAI](https://platform.openai.com/docs/guides/your-data). +- API Anthropic : Les demandes sont conservées pendant 30 jours conformément aux [Politiques de données d'Anthropic](https://docs.anthropic.com/en/docs/claude-code/data-usage). --- ## Pour les équipes -Zen fonctionne également très bien pour les équipes. Vous pouvez inviter des coéquipiers, attribuer des rôles, organiser -les modèles utilisés par votre équipe, et bien plus encore. +Zen fonctionne également très bien pour les équipes. Vous pouvez inviter des coéquipiers, attribuer des rôles, organiser les modèles utilisés par votre équipe, et bien plus encore. :::note Les espaces de travail sont actuellement gratuits pour les équipes dans le cadre de la version bêta. ::: -La gestion de votre espace de travail est actuellement gratuite pour les équipes dans le cadre de la version bêta. Nous serons -partagera bientôt plus de détails sur les prix. +La gestion de votre espace de travail est actuellement gratuite pour les équipes dans le cadre de la version bêta. Nous partagerons bientôt plus de détails sur les prix. --- ### Rôles -Vous pouvez inviter des coéquipiers dans votre espace de travail et attribuer des rôles : +Vous pouvez inviter des coéquipiers dans votre espace de travail et attribuer des rôles : -- **Administrateur** : gérez les modèles, les membres, les clés API et la facturation. -- **Membre** : gérer uniquement ses propres clés API +- **Administrateur** : gérez les modèles, les membres, les clés API et la facturation. +- **Membre** : gérer uniquement ses propres clés API Les administrateurs peuvent également définir des limites de dépenses mensuelles pour chaque membre afin de garder les coûts sous contrôle. @@ -228,8 +216,7 @@ Les administrateurs peuvent également définir des limites de dépenses mensuel Les administrateurs peuvent activer ou désactiver des modèles spécifiques pour l'espace de travail. Les requêtes adressées à un modèle désactivé renverront une erreur. -Ceci est utile dans les cas où vous souhaitez désactiver l'utilisation d'un modèle qui -collecte des données. +Ceci est utile dans les cas où vous souhaitez désactiver l'utilisation d'un modèle qui collecte des données. --- @@ -239,8 +226,7 @@ Vous pouvez utiliser vos propres clés OpenAI ou Anthropic API tout en accédant Lorsque vous utilisez vos propres clés, les tokens sont facturés directement par le fournisseur et non par Zen. -Par exemple, votre organisation dispose peut-être déjà d'une clé pour OpenAI ou Anthropic -et vous souhaitez l'utiliser à la place de celui fourni par Zen. +Par exemple, votre organisation dispose peut-être déjà d'une clé pour OpenAI ou Anthropic et vous souhaitez l'utiliser à la place de celui fourni par Zen. --- @@ -250,5 +236,5 @@ Nous avons créé OpenCode Zen pour : 1. **Benchmark** les meilleurs modèles/fournisseurs d'agents de codage. 2. Ayez accès aux options de **la plus haute qualité** et ne dégradez pas les performances ni ne vous dirigez vers des fournisseurs moins chers. -3. Répercutez toute **baisse de prix** en vendant au prix coûtant ; la seule majoration est donc pour couvrir nos frais de traitement. +3. Répercutez toute **baisse de prix** en vendant au prix coûtant ; la seule majoration est donc pour couvrir nos frais de traitement. 4. N'ayez **aucun verrouillage** en vous permettant de l'utiliser avec n'importe quel autre agent de codage. Et laissez-vous toujours utiliser n'importe quel autre fournisseur avec OpenCode également. diff --git a/packages/web/src/content/docs/go.mdx b/packages/web/src/content/docs/go.mdx new file mode 100644 index 0000000000..5976f1a358 --- /dev/null +++ b/packages/web/src/content/docs/go.mdx @@ -0,0 +1,147 @@ +--- +title: Go +description: Low cost subscription for open coding models. +--- + +import config from "../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go is a low cost **$10/month** subscription that gives you reliable access to popular open coding models. + +:::note +OpenCode Go is currently in beta. +::: + +Go works like any other provider in OpenCode. You subscribe to OpenCode Go and +get your API key. It's **completely optional** and you don't need to use it to +use OpenCode. + +It is designed primarily for international users, with models hosted in the US, EU, and Singapore for stable global access. + +--- + +## Background + +Open models have gotten really good. They now reach performance close to +proprietary models for coding tasks. And because many providers can serve them +competitively, they are usually far cheaper. + +However, getting reliable, low latency access to them can be difficult. Providers +vary in quality and availability. + +:::tip +We tested a select group of models and providers that work well with OpenCode. +::: + +To fix this, we did a couple of things: + +1. We tested a select group of open models and talked to their teams about how to + best run them. +2. We then worked with a few providers to make sure these were being served + correctly. +3. Finally, we benchmarked the combination of the model/provider and came up + with a list that we feel good recommending. + +OpenCode Go gives you access to these models for **$10/month**. + +--- + +## How it works + +OpenCode Go works like any other provider in OpenCode. + +1. You sign in to **OpenCode Zen**, subscribe to Go, and + copy your API key. +2. You run the `/connect` command in the TUI, select `OpenCode Go`, and paste + your API key. +3. Run `/models` in the TUI to see the list of models available through Go. + +:::note +Only one member per workspace can subscribe to OpenCode Go. +::: + +The current list of models includes: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +The list of models may change as we test and add new ones. + +--- + +## Usage limits + +OpenCode Go includes the following limits: + +- **5 hour limit** — $12 of usage +- **Weekly limit** — $30 of usage +- **Monthly limit** — $60 of usage + +Limits are defined in dollar value. This means your actual request count depends on the model you use. Cheaper models like MiniMax M2.5 allow for more requests, while higher-cost models like GLM-5 allow for fewer. + +The table below provides an estimated request count based on typical Go usage patterns: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ------------------- | ----- | --------- | ------------ | +| requests per 5 hour | 1,150 | 1,850 | 20,000 | +| requests per week | 2,880 | 4,630 | 50,000 | +| requests per month | 5,750 | 9,250 | 100,000 | + +Estimates are based on observed average request patterns: + +- GLM-5 — 700 input, 52,000 cached, 150 output tokens per request +- Kimi K2.5 — 870 input, 55,000 cached, 200 output tokens per request +- MiniMax M2.5 — 300 input, 55,000 cached, 125 output tokens per request + +You can track your current usage in the **console**. + +:::tip +If you reach the usage limit, you can continue using the free models. +::: + +Usage limits may change as we learn from early usage and feedback. + +--- + +### Usage beyond limits + +If you also have credits on your Zen balance, you can enable the **Use balance** +option in the console. When enabled, Go will fall back to your Zen balance +after you've reached your usage limits instead of blocking requests. + +--- + +## Endpoints + +You can also access Go models through the following API endpoints. + +| Model | Model ID | Endpoint | AI SDK Package | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +The [model id](/docs/config/#models) in your OpenCode config +uses the format `opencode-go/`. For example, for Kimi K2.5, you would +use `opencode-go/kimi-k2.5` in your config. + +--- + +## Privacy + +The plan is designed primarily for international users, with models hosted in the US, EU, and Singapore for stable global access. + +Contact us if you have any questions. + +--- + +## Goals + +We created OpenCode Go to: + +1. Make AI coding **accessible** to more people with a low cost subscription. +2. Provide **reliable** access to the best open coding models. +3. Curate models that are **tested and benchmarked** for coding agent use. +4. Have **no lock-in** by allowing you to use any other provider with OpenCode as well. diff --git a/packages/web/src/content/docs/it/cli.mdx b/packages/web/src/content/docs/it/cli.mdx index a97bbde1c9..b35292a0a5 100644 --- a/packages/web/src/content/docs/it/cli.mdx +++ b/packages/web/src/content/docs/it/cli.mdx @@ -558,6 +558,7 @@ OpenCode può essere configurato tramite variabili d'ambiente. | `OPENCODE_AUTO_SHARE` | boolean | Condivide automaticamente le sessioni | | `OPENCODE_GIT_BASH_PATH` | string | Percorso all'eseguibile Git Bash su Windows | | `OPENCODE_CONFIG` | string | Percorso al file di configurazione | +| `OPENCODE_TUI_CONFIG` | string | Percorso al file di configurazione TUI | | `OPENCODE_CONFIG_DIR` | string | Percorso alla directory di configurazione | | `OPENCODE_CONFIG_CONTENT` | string | Contenuto JSON di config inline | | `OPENCODE_DISABLE_AUTOUPDATE` | boolean | Disabilita i controlli automatici di aggiornamento | diff --git a/packages/web/src/content/docs/it/config.mdx b/packages/web/src/content/docs/it/config.mdx index c94cc59a9b..05741e172e 100644 --- a/packages/web/src/content/docs/it/config.mdx +++ b/packages/web/src/content/docs/it/config.mdx @@ -14,10 +14,11 @@ OpenCode supporta sia **JSON** sia **JSONC** (JSON con commenti). ```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", - // Theme configuration - "theme": "opencode", "model": "anthropic/claude-sonnet-4-5", "autoupdate": true, + "server": { + "port": 4096, + }, } ``` @@ -33,7 +34,7 @@ I file di configurazione vengono **uniti (merge)**, non sostituiti. I file di configurazione vengono uniti (merge), non sostituiti. Le impostazioni provenienti dalle posizioni qui sotto vengono combinate. Le configurazioni caricate dopo sovrascrivono quelle precedenti solo per le chiavi in conflitto. Le impostazioni non in conflitto vengono preservate. -Per esempio, se la tua configurazione globale imposta `theme: "opencode"` e `autoupdate: true`, e la configurazione del progetto imposta `model: "anthropic/claude-sonnet-4-5"`, la configurazione finale includera tutte e tre le impostazioni. +Per esempio, se la tua configurazione globale imposta `autoupdate: true` e la configurazione del progetto imposta `model: "anthropic/claude-sonnet-4-5"`, la configurazione finale includera entrambe le impostazioni. --- @@ -94,7 +95,9 @@ Puoi abilitare server specifici nella tua configurazione locale: ### Configurazione globale -Metti la configurazione globale di OpenCode in `~/.config/opencode/opencode.json`. Usa la configurazione globale per preferenze valide per l'utente (ad es. temi, provider o keybind). +Metti la configurazione globale di OpenCode in `~/.config/opencode/opencode.json`. Usa la configurazione globale per preferenze server/runtime valide per l'utente come provider, modelli e permessi. + +Per le impostazioni specifiche della TUI, usa `~/.config/opencode/tui.json`. La configurazione globale sovrascrive i default remoti dell'organizzazione. @@ -104,6 +107,8 @@ La configurazione globale sovrascrive i default remoti dell'organizzazione. Aggiungi `opencode.json` nella root del progetto. La configurazione di progetto ha la precedenza piu alta tra i file standard: sovrascrive sia la configurazione globale sia quella remota. +Per le impostazioni TUI specifiche del progetto, aggiungi `tui.json` nella stessa posizione. + :::tip Metti la configurazione specifica del progetto nella root del progetto. ::: @@ -144,34 +149,32 @@ La directory personalizzata viene caricata dopo la configurazione globale e le d Il file di configurazione ha uno schema definito in [**`opencode.ai/config.json`**](https://opencode.ai/config.json). +La configurazione TUI usa [**`opencode.ai/tui.json`**](https://opencode.ai/tui.json). + Il tuo editor dovrebbe poter validare e suggerire l'autocompletamento in base allo schema. --- ### TUI -Puoi configurare impostazioni specifiche della TUI tramite l'opzione `tui`. +Usa un file dedicato `tui.json` (o `tui.jsonc`) per le impostazioni specifiche della TUI. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - }, - "diff_style": "auto" - } + "$schema": "https://opencode.ai/tui.json", + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` -Opzioni disponibili: +Usa `OPENCODE_TUI_CONFIG` per puntare a un file di configurazione TUI personalizzato. -- `scroll_acceleration.enabled` - Abilita l'accelerazione di scorrimento in stile macOS. **Ha precedenza su `scroll_speed`.** -- `scroll_speed` - Moltiplicatore personalizzato della velocita di scorrimento (predefinito: `3`, minimo: `1`). Ignorato se `scroll_acceleration.enabled` e `true`. -- `diff_style` - Controlla la resa delle diff. `"auto"` si adatta alla larghezza del terminale, `"stacked"` mostra sempre una singola colonna. +Le chiavi legacy `theme`, `keybinds` e `tui` in `opencode.json` sono deprecate e vengono migrate automaticamente quando possibile. -[Scopri di piu sull'uso della TUI](/docs/tui). +[Scopri di piu sulla configurazione TUI](/docs/tui#configure). --- @@ -297,12 +300,12 @@ I bearer token (`AWS_BEARER_TOKEN_BEDROCK` o `/connect`) hanno precedenza sull'a ### Temi -Puoi configurare il tema da usare in OpenCode tramite l'opzione `theme`. +Imposta il tuo tema UI in `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "theme": "" + "$schema": "https://opencode.ai/tui.json", + "theme": "tokyonight" } ``` @@ -402,11 +405,11 @@ Puoi anche definire comandi usando file markdown in `~/.config/opencode/commands ### Scorciatoie -Puoi personalizzare i keybind tramite l'opzione `keybinds`. +Personalizza i keybind in `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": {} } ``` @@ -486,13 +489,15 @@ Puoi controllare il comportamento di compattazione del contesto tramite l'opzion "$schema": "https://opencode.ai/config.json", "compaction": { "auto": true, - "prune": true + "prune": true, + "reserved": 10000 } } ``` - `auto` - Compatta automaticamente la sessione quando il contesto e pieno (predefinito: `true`). - `prune` - Rimuove output vecchi degli strumenti per risparmiare token (predefinito: `true`). +- `reserved` - Token buffer per la compattazione. Lascia abbastanza margine per evitare overflow durante la compattazione --- diff --git a/packages/web/src/content/docs/it/custom-tools.mdx b/packages/web/src/content/docs/it/custom-tools.mdx index 43f69c43c6..a0ef1c46c2 100644 --- a/packages/web/src/content/docs/it/custom-tools.mdx +++ b/packages/web/src/content/docs/it/custom-tools.mdx @@ -79,6 +79,32 @@ Questo crea due strumenti: `math_add` e `math_multiply`. --- +#### Collisioni di nomi con strumenti integrati + +Gli strumenti personalizzati sono indicizzati per nome. Se uno strumento personalizzato usa lo stesso nome di uno strumento integrato, quello personalizzato ha la precedenza. + +Per esempio, questo file sostituisce lo strumento `bash` integrato: + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +Preferisci nomi univoci a meno che tu non voglia intenzionalmente sostituire uno strumento integrato. Se vuoi disabilitare uno strumento integrato ma non sovrascriverlo, usa i [permessi](/docs/permissions). +::: + +--- + ### Argomenti Puoi usare `tool.schema`, che e semplicemente [Zod](https://zod.dev), per definire i tipi degli argomenti. diff --git a/packages/web/src/content/docs/it/formatters.mdx b/packages/web/src/content/docs/it/formatters.mdx index c264da3f4b..58e4c60ed0 100644 --- a/packages/web/src/content/docs/it/formatters.mdx +++ b/packages/web/src/content/docs/it/formatters.mdx @@ -11,33 +11,34 @@ OpenCode formatta automaticamente i file dopo che vengono scritti o modificati u OpenCode include diversi formattatori integrati per linguaggi e framework popolari. Qui sotto trovi la lista dei formattatori, delle estensioni supportate e dei comandi o opzioni di config richiesti. -| Formattatore | Estensioni | Requisiti | -| -------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -| gofmt | .go | `gofmt` command available | -| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | `mix` command available | -| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://prettier.io/docs/en/index.html) | `prettier` dependency in `package.json` | -| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://biomejs.dev/) | `biome.json(c)` config file | -| zig | .zig, .zon | `zig` command available | -| clang-format | .c, .cpp, .h, .hpp, .ino, and [more](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` config file | -| ktlint | .kt, .kts | `ktlint` command available | -| ruff | .py, .pyi | `ruff` command available with config | -| rustfmt | .rs | `rustfmt` command available | -| cargofmt | .rs | `cargo fmt` command available | -| uv | .py, .pyi | `uv` command available | -| rubocop | .rb, .rake, .gemspec, .ru | `rubocop` command available | -| standardrb | .rb, .rake, .gemspec, .ru | `standardrb` command available | -| htmlbeautifier | .erb, .html.erb | `htmlbeautifier` command available | -| air | .R | `air` command available | -| dart | .dart | `dart` command available | -| dfmt | .d | `dfmt` command available | -| ocamlformat | .ml, .mli | `ocamlformat` command available and `.ocamlformat` config file | -| terraform | .tf, .tfvars | `terraform` command available | -| gleam | .gleam | `gleam` command available | -| nixfmt | .nix | `nixfmt` command available | -| shfmt | .sh, .bash | `shfmt` command available | -| pint | .php | `laravel/pint` dependency in `composer.json` | -| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | `oxfmt` dependency in `package.json` and an [experimental env variable flag](/docs/cli/#experimental) | -| ormolu | .hs | `ormolu` command available | +| Formattatore | Estensioni | Requisiti | +| -------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| air | .R | comando `air` disponibile | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://biomejs.dev/) | file di configurazione `biome.json(c)` | +| cargofmt | .rs | comando `cargo fmt` disponibile | +| clang-format | .c, .cpp, .h, .hpp, .ino, and [more](https://clang.llvm.org/docs/ClangFormat.html) | file di configurazione `.clang-format` | +| cljfmt | .clj, .cljs, .cljc, .edn | comando `cljfmt` disponibile | +| dart | .dart | comando `dart` disponibile | +| dfmt | .d | comando `dfmt` disponibile | +| gleam | .gleam | comando `gleam` disponibile | +| gofmt | .go | comando `gofmt` disponibile | +| htmlbeautifier | .erb, .html.erb | comando `htmlbeautifier` disponibile | +| ktlint | .kt, .kts | comando `ktlint` disponibile | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | comando `mix` disponibile | +| nixfmt | .nix | comando `nixfmt` disponibile | +| ocamlformat | .ml, .mli | comando `ocamlformat` disponibile e file di configurazione `.ocamlformat` | +| ormolu | .hs | comando `ormolu` disponibile | +| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | dipendenza `oxfmt` in `package.json` e una [flag variabile d'ambiente sperimentale](/docs/cli/#experimental) | +| pint | .php | dipendenza `laravel/pint` in `composer.json` | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://prettier.io/docs/en/index.html) | dipendenza `prettier` in `package.json` | +| rubocop | .rb, .rake, .gemspec, .ru | comando `rubocop` disponibile | +| ruff | .py, .pyi | comando `ruff` disponibile con config | +| rustfmt | .rs | comando `rustfmt` disponibile | +| shfmt | .sh, .bash | comando `shfmt` disponibile | +| standardrb | .rb, .rake, .gemspec, .ru | comando `standardrb` disponibile | +| terraform | .tf, .tfvars | comando `terraform` disponibile | +| uv | .py, .pyi | comando `uv` disponibile | +| zig | .zig, .zon | comando `zig` disponibile | Quindi, se il progetto ha `prettier` in `package.json`, OpenCode lo usera automaticamente. diff --git a/packages/web/src/content/docs/it/go.mdx b/packages/web/src/content/docs/it/go.mdx new file mode 100644 index 0000000000..912cd29004 --- /dev/null +++ b/packages/web/src/content/docs/it/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: Abbonamento a basso costo per modelli di coding open source. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go è un abbonamento a basso costo di **$10/mese** che ti offre un accesso affidabile ai modelli di coding open source più popolari. + +:::note +OpenCode Go è attualmente in beta. +::: + +Go funziona come qualsiasi altro provider in OpenCode. Ti abboni a OpenCode Go e ottieni la tua chiave API. È **completamente opzionale** e non è necessario utilizzarlo per usare OpenCode. + +È progettato principalmente per utenti internazionali, con modelli ospitati negli Stati Uniti, UE e Singapore per un accesso globale stabile. + +--- + +## Contesto + +I modelli open source sono diventati davvero validi. Ora raggiungono prestazioni vicine ai modelli proprietari per le attività di coding. E poiché molti provider possono servirli in modo competitivo, sono solitamente molto più economici. + +Tuttavia, ottenere un accesso affidabile e a bassa latenza può essere difficile. I provider variano in termini di qualità e disponibilità. + +:::tip +Abbiamo testato un gruppo selezionato di modelli e provider che funzionano bene con OpenCode. +::: + +Per risolvere questo problema, abbiamo fatto un paio di cose: + +1. Abbiamo testato un gruppo selezionato di modelli open source e parlato con i loro team su come eseguirli al meglio. +2. Abbiamo poi lavorato con alcuni provider per assicurarci che questi venissero serviti correttamente. +3. Infine, abbiamo effettuato benchmark sulla combinazione modello/provider e abbiamo stilato un elenco che ci sentiamo di raccomandare. + +OpenCode Go ti dà accesso a questi modelli per **$10/mese**. + +--- + +## Come funziona + +OpenCode Go funziona come qualsiasi altro provider in OpenCode. + +1. Accedi a **OpenCode Zen**, abbonati a Go e copia la tua chiave API. +2. Esegui il comando `/connect` nella TUI, seleziona `OpenCode Go` e incolla la tua chiave API. +3. Esegui `/models` nella TUI per vedere l'elenco dei modelli disponibili tramite Go. + +:::note +Solo un membro per workspace può abbonarsi a OpenCode Go. +::: + +L'elenco attuale dei modelli include: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +L'elenco dei modelli potrebbe cambiare man mano che ne testiamo e aggiungiamo di nuovi. + +--- + +## Limiti di utilizzo + +OpenCode Go include i seguenti limiti: + +- **Limite di 5 ore** — $12 di utilizzo +- **Limite settimanale** — $30 di utilizzo +- **Limite mensile** — $60 di utilizzo + +I limiti sono definiti in valore monetario. Ciò significa che il conteggio effettivo delle richieste dipende dal modello utilizzato. Modelli più economici come MiniMax M2.5 consentono più richieste, mentre modelli più costosi come GLM-5 ne consentono meno. + +La tabella seguente fornisce una stima del conteggio delle richieste basata su tipici modelli di utilizzo di Go: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| --------------------- | ----- | --------- | ------------ | +| richieste ogni 5 ore | 1.150 | 1.850 | 30.000 | +| richieste a settimana | 2.880 | 4.630 | 75.000 | +| richieste al mese | 5.750 | 9.250 | 150.000 | + +Le stime si basano sui modelli di richiesta medi osservati: + +- GLM-5 — 700 input, 52.000 cached, 150 output tokens per richiesta +- Kimi K2.5 — 870 input, 55.000 cached, 200 output tokens per richiesta +- MiniMax M2.5 — 300 input, 55.000 cached, 125 output tokens per richiesta + +Puoi monitorare il tuo utilizzo attuale nella **console**. + +:::tip +Se raggiungi il limite di utilizzo, puoi continuare a utilizzare i modelli gratuiti. +::: + +I limiti di utilizzo potrebbero cambiare man mano che impariamo dall'utilizzo iniziale e dai feedback. + +--- + +### Prezzi + +OpenCode Go è un piano di abbonamento da **$10/mese**. Di seguito sono riportati i prezzi **per 1M di token**. + +| Modello | Input | Output | Lettura Cached | +| ------------ | ----- | ------ | -------------- | +| GLM-5 | $1.00 | $3.20 | $0.20 | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | +| MiniMax M2.5 | $0.30 | $1.20 | $0.03 | + +--- + +### Utilizzo oltre i limiti + +Se hai anche crediti sul tuo saldo Zen, puoi abilitare l'opzione **Use balance** nella console. Quando abilitata, Go utilizzerà il tuo saldo Zen dopo aver raggiunto i limiti di utilizzo invece di bloccare le richieste. + +--- + +## Endpoint + +Puoi anche accedere ai modelli Go tramite i seguenti endpoint API. + +| Modello | ID Modello | Endpoint | Pacchetto AI SDK | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +Il [model id](/docs/config/#models) nella tua configurazione OpenCode utilizza il formato `opencode-go/`. Ad esempio, per Kimi K2.5, useresti `opencode-go/kimi-k2.5` nella tua configurazione. + +--- + +## Privacy + +Il piano è progettato principalmente per utenti internazionali, con modelli ospitati negli Stati Uniti, UE e Singapore per un accesso globale stabile. + +Contattaci se hai domande. + +--- + +## Obiettivi + +Abbiamo creato OpenCode Go per: + +1. Rendere l'AI per il coding **accessibile** a più persone con un abbonamento a basso costo. +2. Fornire un accesso **affidabile** ai migliori modelli di coding open source. +3. Curare modelli che sono **testati e benchmarked** per l'uso con agenti di coding. +4. Non avere **alcun lock-in** permettendoti di utilizzare qualsiasi altro provider con OpenCode. diff --git a/packages/web/src/content/docs/it/keybinds.mdx b/packages/web/src/content/docs/it/keybinds.mdx index eb08c2c286..548805e6ba 100644 --- a/packages/web/src/content/docs/it/keybinds.mdx +++ b/packages/web/src/content/docs/it/keybinds.mdx @@ -3,11 +3,11 @@ title: Scorciatoie description: Personalizza le scorciatoie da tastiera. --- -OpenCode ha una lista di scorciatoie che puoi personalizzare tramite la configurazione di OpenCode. +OpenCode ha una lista di scorciatoie che puoi personalizzare tramite `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -117,11 +117,11 @@ Non sei obbligato a usare un tasto leader per le scorciatoie, ma lo consigliamo. ## Disabilitare una scorciatoia -Puoi disabilitare una scorciatoia aggiungendo la chiave nella configurazione con valore "none". +Puoi disabilitare una scorciatoia aggiungendo la chiave in `tui.json` con valore "none". -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/it/lsp.mdx b/packages/web/src/content/docs/it/lsp.mdx index 765475dba0..a21133b141 100644 --- a/packages/web/src/content/docs/it/lsp.mdx +++ b/packages/web/src/content/docs/it/lsp.mdx @@ -27,6 +27,7 @@ OpenCode include diversi server LSP integrati per linguaggi popolari: | gopls | .go | comando `go` disponibile | | hls | .hs, .lhs | comando `haskell-language-server-wrapper` disponibile | | jdtls | .java | `Java SDK (version 21+)` installato | +| julials | .jl | `julia` e `LanguageServer.jl` installati | | kotlin-ls | .kt, .kts | Installazione automatica per progetti Kotlin | | lua-ls | .lua | Installazione automatica per progetti Lua | | nixd | .nix | comando `nixd` disponibile | diff --git a/packages/web/src/content/docs/it/plugins.mdx b/packages/web/src/content/docs/it/plugins.mdx index ea73f40ffd..3fc22a78c5 100644 --- a/packages/web/src/content/docs/it/plugins.mdx +++ b/packages/web/src/content/docs/it/plugins.mdx @@ -3,7 +3,7 @@ title: Plugin description: Scrivi plugin per estendere OpenCode. --- -I plugin ti permettono di estendere OpenCode agganciandoti a vari eventi e personalizzando il comportamento. Puoi creare plugin per aggiungere nuove funzionalita', integrare servizi esterni o modificare il comportamento predefinito di OpenCode. +I plugin ti permettono di estendere OpenCode agganciandoti a vari eventi e personalizzando il comportamento. Puoi creare plugin per aggiungere nuove funzionalità, integrare servizi esterni o modificare il comportamento predefinito di OpenCode. Per esempi, dai un'occhiata ai [plugin](/docs/ecosystem#plugins) creati dalla community. @@ -53,7 +53,7 @@ I **plugin locali** vengono caricati direttamente dalla directory dei plugin. Pe ### Ordine di caricamento -I plugin vengono caricati da tutte le sorgenti e tutti gli hook vengono eseguiti in sequenza. L'ordine di caricamento e': +I plugin vengono caricati da tutte le sorgenti e tutti gli hook vengono eseguiti in sequenza. L'ordine di caricamento è: 1. Config globale (`~/.config/opencode/opencode.json`) 2. Config di progetto (`opencode.json`) @@ -66,7 +66,7 @@ I pacchetti npm duplicati con lo stesso nome e versione vengono caricati una sol ## Creare un plugin -Un plugin e' un **modulo JavaScript/TypeScript** che esporta una o piu' funzioni di plugin. Ogni funzione riceve un oggetto di contesto e restituisce un oggetto di hook. +Un plugin è un **modulo JavaScript/TypeScript** che esporta una o più funzioni di plugin. Ogni funzione riceve un oggetto di contesto e restituisce un oggetto di hook. --- @@ -234,7 +234,7 @@ export const NotificationPlugin = async ({ project, client, $, directory, worktr Stiamo usando `osascript` per eseguire AppleScript su macOS. Qui lo usiamo per inviare notifiche. :::note -Se usi l'app desktop di OpenCode, puo' inviare automaticamente notifiche di sistema quando una risposta e' pronta o quando una sessione va in errore. +Se usi l'app desktop di OpenCode, può inviare automaticamente notifiche di sistema quando una risposta è pronta o quando una sessione va in errore. ::: --- @@ -299,7 +299,7 @@ export const CustomToolsPlugin: Plugin = async (ctx) => { } ``` -L'helper `tool` crea uno strumento personalizzato che opencode puo' chiamare. Accetta una funzione di schema Zod e restituisce una definizione di tool con: +L'helper `tool` crea uno strumento personalizzato che opencode può chiamare. Accetta una funzione di schema Zod e restituisce una definizione di tool con: - `description`: cosa fa lo strumento - `args`: schema Zod per gli argomenti dello strumento @@ -307,6 +307,10 @@ L'helper `tool` crea uno strumento personalizzato che opencode puo' chiamare. Ac I tuoi strumenti personalizzati saranno disponibili in opencode insieme agli strumenti integrati. +:::note +Se uno strumento di un plugin usa lo stesso nome di uno strumento integrato, lo strumento del plugin ha la precedenza. +::: + --- ### Logging @@ -381,4 +385,4 @@ Format as a structured prompt that a new agent can use to resume work. } ``` -Quando `output.prompt` e' impostato, sostituisce completamente il prompt di compaction predefinito. In questo caso l'array `output.context` viene ignorato. +Quando `output.prompt` è impostato, sostituisce completamente il prompt di compaction predefinito. In questo caso l'array `output.context` viene ignorato. diff --git a/packages/web/src/content/docs/it/providers.mdx b/packages/web/src/content/docs/it/providers.mdx index 9b4c07b665..c0c5489d08 100644 --- a/packages/web/src/content/docs/it/providers.mdx +++ b/packages/web/src/content/docs/it/providers.mdx @@ -818,7 +818,7 @@ Alcuni modelli devono essere abilitati manualmente nelle tue [impostazioni GitHu │ │ Enter code: 8F43-6FCF │ - └ Waiting for authorization... + │ └ Waiting for authorization... ``` 3. Ora esegui il comando `/models` per selezionare il modello che vuoi. @@ -1488,6 +1488,39 @@ SAP AI Core fornisce accesso a oltre 40 modelli di OpenAI, Anthropic, Google, Am --- +### STACKIT + +STACKIT AI Model Serving fornisce un ambiente di hosting completamente gestito e sovrano per modelli AI, concentrandosi su LLM come Llama, Mistral e Qwen, con la massima sovranità dei dati su infrastruttura europea. + +1. Vai al [Portale STACKIT](https://portal.stackit.cloud), naviga in **AI Model Serving** e crea un token di autenticazione per il tuo progetto. + + :::tip + Devi avere un account cliente STACKIT, un account utente e un progetto prima di creare token di autenticazione. + ::: + +2. Esegui il comando `/connect` e cerca **STACKIT**. + + ```txt + /connect + ``` + +3. Inserisci il tuo token di autenticazione STACKIT AI Model Serving. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Esegui il comando `/models` per selezionare tra i modelli disponibili come _Qwen3-VL 235B_ o _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + ### OVHcloud AI Endpoints 1. Vai al [pannello OVHcloud](https://ovh.com/manager). Naviga nella sezione `Public Cloud`, `AI & Machine Learning` > `AI Endpoints` e nella scheda `API Keys`, clicca **Create a new API key**. diff --git a/packages/web/src/content/docs/it/sdk.mdx b/packages/web/src/content/docs/it/sdk.mdx index 9cf7e4eae5..2941bfb24c 100644 --- a/packages/web/src/content/docs/it/sdk.mdx +++ b/packages/web/src/content/docs/it/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## Output Strutturato + +Puoi richiedere un output JSON strutturato dal modello specificando un `format` con uno schema JSON. Il modello usera un tool `StructuredOutput` per restituire JSON validato che corrisponde al tuo schema. + +### Uso Base + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Access the structured output +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### Tipi di Formato Output + +| Tipo | Descrizione | +| ------------- | ------------------------------------------------------------------- | +| `text` | Predefinito. Risposta di testo standard (nessun output strutturato) | +| `json_schema` | Restituisce JSON validato che corrisponde allo schema fornito | + +### Formato Schema JSON + +Quando usi `type: 'json_schema'`, fornisci: + +| Campo | Tipo | Descrizione | +| ------------ | --------------- | --------------------------------------------------------------------- | +| `type` | `'json_schema'` | Richiesto. Specifica la modalita schema JSON | +| `schema` | `object` | Richiesto. Oggetto JSON Schema che definisce la struttura dell'output | +| `retryCount` | `number` | Opzionale. Numero di tentativi di validazione (default: 2) | + +### Gestione Errori + +Se il modello non riesce a produrre un output strutturato valido dopo tutti i tentativi, la risposta includera un `StructuredOutputError`: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### Best Practices + +1. **Fornisci descrizioni chiare** nelle proprieta del tuo schema per aiutare il modello a capire quali dati estrarre +2. **Usa `required`** per specificare quali campi devono essere presenti +3. **Mantieni gli schemi focalizzati** - schemi annidati complessi potrebbero essere piu difficili da compilare correttamente per il modello +4. **Imposta un `retryCount` appropriato** - aumenta per schemi complessi, diminuisci per quelli semplici + +--- + ## API L'SDK espone tutte le API del server tramite un client type-safe. @@ -226,27 +298,27 @@ const { providers, default: defaults } = await client.config.providers() ### Sessioni -| Metodo | Descrizione | Note | -| ---------------------------------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | Elenca le sessioni | Returns Session[] | -| `session.get({ path })` | Ottieni una sessione | Returns Session | -| `session.children({ path })` | Elenca sessioni figlie | Returns Session[] | -| `session.create({ body })` | Crea una sessione | Returns Session | -| `session.delete({ path })` | Elimina una sessione | Returns `boolean` | -| `session.update({ path, body })` | Aggiorna proprieta della sessione | Returns Session | -| `session.init({ path, body })` | Analizza app e crea `AGENTS.md` | Returns `boolean` | -| `session.abort({ path })` | Interrompe una sessione in corso | Returns `boolean` | -| `session.share({ path })` | Condivide la sessione | Returns Session | -| `session.unshare({ path })` | Rimuove la condivisione | Returns Session | -| `session.summarize({ path, body })` | Riassume la sessione | Returns `boolean` | -| `session.messages({ path })` | Elenca i messaggi della sessione | Returns `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ path })` | Ottieni dettagli di un messaggio | Returns `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | Invia un prompt | `body.noReply: true` returns UserMessage (solo contesto). Di default ritorna AssistantMessage con risposta AI | -| `session.command({ path, body })` | Invia un comando alla sessione | Returns `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | Esegue un comando shell | Returns AssistantMessage | -| `session.revert({ path, body })` | Ripristina un messaggio | Returns Session | -| `session.unrevert({ path })` | Ripristina messaggi revertiti | Returns Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | Risponde a una richiesta permessi | Returns `boolean` | +| Metodo | Descrizione | Note | +| ---------------------------------------------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | Elenca le sessioni | Returns Session[] | +| `session.get({ path })` | Ottieni una sessione | Returns Session | +| `session.children({ path })` | Elenca sessioni figlie | Returns Session[] | +| `session.create({ body })` | Crea una sessione | Returns Session | +| `session.delete({ path })` | Elimina una sessione | Returns `boolean` | +| `session.update({ path, body })` | Aggiorna proprieta della sessione | Returns Session | +| `session.init({ path, body })` | Analizza app e crea `AGENTS.md` | Returns `boolean` | +| `session.abort({ path })` | Interrompe una sessione in corso | Returns `boolean` | +| `session.share({ path })` | Condivide la sessione | Returns Session | +| `session.unshare({ path })` | Rimuove la condivisione | Returns Session | +| `session.summarize({ path, body })` | Riassume la sessione | Returns `boolean` | +| `session.messages({ path })` | Elenca i messaggi della sessione | Returns `{ info: `Message`, parts: `Part[]`}[]` | +| `session.message({ path })` | Ottieni dettagli di un messaggio | Returns `{ info: `Message`, parts: `Part[]`}` | +| `session.prompt({ path, body })` | Invia un prompt | `body.noReply: true` returns UserMessage (solo contesto). Di default ritorna AssistantMessage con risposta AI. Supporta `body.outputFormat` per [output strutturato](#output-strutturato) | +| `session.command({ path, body })` | Invia un comando alla sessione | Returns `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `session.shell({ path, body })` | Esegue un comando shell | Returns AssistantMessage | +| `session.revert({ path, body })` | Ripristina un messaggio | Returns Session | +| `session.unrevert({ path })` | Ripristina messaggi revertiti | Returns Session | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | Risponde a una richiesta permessi | Returns `boolean` | --- diff --git a/packages/web/src/content/docs/it/themes.mdx b/packages/web/src/content/docs/it/themes.mdx index 6752470e0f..055e108727 100644 --- a/packages/web/src/content/docs/it/themes.mdx +++ b/packages/web/src/content/docs/it/themes.mdx @@ -45,13 +45,13 @@ E altri ancora: aggiungiamo costantemente nuovi temi. ## Tema di sistema -Il tema `system` e progettato per adattarsi automaticamente allo schema colori del tuo terminale. A differenza dei temi tradizionali con colori fissi, il tema _system_: +Il tema `system` è progettato per adattarsi automaticamente allo schema colori del tuo terminale. A differenza dei temi tradizionali con colori fissi, il tema _system_: - **Genera una scala di grigi**: crea una scala di grigi personalizzata in base al colore di sfondo del terminale, garantendo un contrasto ottimale. - **Usa colori ANSI**: sfrutta i colori ANSI standard (0-15) per evidenziazione della sintassi ed elementi UI, rispettando la palette del terminale. - **Preserva i default del terminale**: usa `none` per testo e sfondo per mantenere l'aspetto nativo del terminale. -Il tema di sistema e pensato per chi: +Il tema di sistema è pensato per chi: - Vuole che OpenCode corrisponda all'aspetto del terminale - Usa schemi colori personalizzati del terminale @@ -61,11 +61,11 @@ Il tema di sistema e pensato per chi: ## Usare un tema -Puoi selezionare un tema aprendo la selezione temi con il comando `/theme`. In alternativa, puoi specificarlo nella tua [configurazione](/docs/config). +Puoi selezionare un tema aprendo la selezione temi con il comando `/theme`. In alternativa, puoi specificarlo in `tui.json`. -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` @@ -80,14 +80,14 @@ OpenCode supporta un sistema di temi flessibile basato su JSON che permette di c ### Gerarchia -I temi vengono caricati da piu directory nel seguente ordine, dove le directory successive sovrascrivono le precedenti: +I temi vengono caricati da più directory nel seguente ordine, dove le directory successive sovrascrivono le precedenti: 1. **Temi integrati** - incorporati nel binario 2. **Directory di configurazione utente** - in `~/.config/opencode/themes/*.json` o `$XDG_CONFIG_HOME/opencode/themes/*.json` 3. **Directory root del progetto** - in `/.opencode/themes/*.json` 4. **Directory di lavoro corrente** - in `./.opencode/themes/*.json` -Se piu directory contengono un tema con lo stesso nome, verra usato il tema della directory con priorita piu alta. +Se più directory contengono un tema con lo stesso nome, verrà usato il tema della directory con priorità più alta. --- @@ -125,13 +125,13 @@ I temi usano un formato JSON flessibile che supporta: ### Definizioni dei colori -La sezione `defs` e opzionale e ti permette di definire colori riutilizzabili che possono essere referenziati nel tema. +La sezione `defs` è opzionale e ti permette di definire colori riutilizzabili che possono essere referenziati nel tema. --- ### Valori predefiniti del terminale -Il valore speciale `"none"` puo essere usato per qualunque colore per ereditare il colore predefinito del terminale. E particolarmente utile per creare temi che si fondono con lo schema colori del terminale: +Il valore speciale `"none"` può essere usato per qualunque colore per ereditare il colore predefinito del terminale. È particolarmente utile per creare temi che si fondono con lo schema colori del terminale: - `"text": "none"` - usa il colore del testo predefinito del terminale - `"background": "none"` - usa il colore di sfondo predefinito del terminale diff --git a/packages/web/src/content/docs/it/troubleshooting.mdx b/packages/web/src/content/docs/it/troubleshooting.mdx index 5140571507..7c168979da 100644 --- a/packages/web/src/content/docs/it/troubleshooting.mdx +++ b/packages/web/src/content/docs/it/troubleshooting.mdx @@ -57,8 +57,8 @@ Se l'app desktop va in crash all'avvio, si blocca o si comporta in modo strano, Apri il tuo file di configurazione globale e cerca la chiave `plugin`. -- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (or `~/.config/opencode/opencode.json`) -- **macOS/Linux** (older installs): `~/.local/share/opencode/opencode.jsonc` +- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (o `~/.config/opencode/opencode.json`) +- **macOS/Linux** (installazioni vecchie): `~/.local/share/opencode/opencode.jsonc` - **Windows**: premi `WIN+R` e incolla `%USERPROFILE%\.config\opencode\opencode.jsonc` Se hai plugin configurati, disabilitali temporaneamente rimuovendo la chiave o impostandola a un array vuoto: @@ -88,14 +88,14 @@ Se l'app ricomincia a funzionare, riabilita i plugin uno alla volta per capire q Se disabilitare i plugin non aiuta (o l'installazione di un plugin e bloccata), svuota la cache in modo che OpenCode possa ricostruirla. -1. Quit OpenCode Desktop completely. +1. Chiudi completamente OpenCode Desktop. 2. Elimina la directory della cache: - **macOS**: Finder -> `Cmd+Shift+G` -> paste `~/.cache/opencode` - **Linux**: elimina `~/.cache/opencode` (oppure esegui `rm -rf ~/.cache/opencode`) - **Windows**: premi `WIN+R` e incolla `%USERPROFILE%\.cache\opencode` -3. Restart OpenCode Desktop. +3. Riavvia OpenCode Desktop. --- @@ -155,7 +155,7 @@ OpenCode Desktop mostra le notifiche di sistema solo quando: Se l'app non si avvia e non riesci a ripulire le impostazioni dall'interfaccia, reimposta lo stato salvato dell'app desktop. -1. Quit OpenCode Desktop. +1. Chiudi OpenCode Desktop. 2. Trova ed elimina questi file (si trovano nella directory dati dell'app OpenCode Desktop): - `opencode.settings.dat` (desktop default server URL) diff --git a/packages/web/src/content/docs/it/tui.mdx b/packages/web/src/content/docs/it/tui.mdx index 8a09c97a3e..2e4efa2608 100644 --- a/packages/web/src/content/docs/it/tui.mdx +++ b/packages/web/src/content/docs/it/tui.mdx @@ -63,7 +63,7 @@ Quando usi la TUI di OpenCode, puoi digitare `/` seguito dal nome di un comando /help ``` -Molti comandi hanno anche una scorciatoia da tastiera che usa `ctrl+x` come tasto leader (predefinito). [Scopri di piu](/docs/keybinds). +Molti comandi hanno anche una scorciatoia da tastiera che usa `ctrl+x` come tasto leader (predefinito). [Scopri di più](/docs/keybinds). Ecco tutti i comandi slash disponibili: @@ -105,7 +105,7 @@ Attiva/disattiva i dettagli di esecuzione degli strumenti. ### editor -Apre un editor esterno per comporre messaggi. Usa l'editor impostato nella variabile d'ambiente `EDITOR`. [Scopri di piu](#editor-setup). +Apre un editor esterno per comporre messaggi. Usa l'editor impostato nella variabile d'ambiente `EDITOR`. [Scopri di più](#editor-setup). ```bash frame="none" /editor @@ -129,7 +129,7 @@ Esce da OpenCode. _Alias_: `/quit`, `/q` ### esporta -Esporta la conversazione corrente in Markdown e la apre nell'editor predefinito. Usa l'editor impostato nella variabile d'ambiente `EDITOR`. [Scopri di piu](#editor-setup). +Esporta la conversazione corrente in Markdown e la apre nell'editor predefinito. Usa l'editor impostato nella variabile d'ambiente `EDITOR`. [Scopri di più](#editor-setup). ```bash frame="none" /export @@ -153,7 +153,7 @@ Mostra la finestra di aiuto. ### inizializza -Crea o aggiorna il file `AGENTS.md`. [Scopri di piu](/docs/rules). +Crea o aggiorna il file `AGENTS.md`. [Scopri di più](/docs/rules). ```bash frame="none" /init @@ -219,7 +219,7 @@ Elenca e passa tra le sessioni. _Alias_: `/resume`, `/continue` ### condividi -Condivide la sessione corrente. [Scopri di piu](/docs/share). +Condivide la sessione corrente. [Scopri di più](/docs/share). ```bash frame="none" /share @@ -234,7 +234,7 @@ Condivide la sessione corrente. [Scopri di piu](/docs/share). Elenca i temi disponibili. ```bash frame="none" -/theme +/themes ``` **Scorciatoia:** `ctrl+x t` @@ -243,10 +243,10 @@ Elenca i temi disponibili. ### ragionamento -Attiva/disattiva la visibilita dei blocchi thinking/reasoning nella conversazione. Quando abilitato, puoi vedere il ragionamento del modello per i modelli che supportano extended thinking. +Attiva/disattiva la visibilità dei blocchi thinking/reasoning nella conversazione. Quando abilitato, puoi vedere il ragionamento del modello per i modelli che supportano extended thinking. :::note -Questo comando controlla solo se i blocchi di thinking vengono **mostrati**: non abilita o disabilita le capacita di ragionamento del modello. Per cambiare le capacita di ragionamento effettive, usa `ctrl+t` per ciclare tra le varianti del modello. +Questo comando controlla solo se i blocchi di thinking vengono **mostrati**: non abilita o disabilita le capacità di ragionamento del modello. Per cambiare le capacità di ragionamento effettive, usa `ctrl+t` per ciclare tra le varianti del modello. ::: ```bash frame="none" @@ -275,7 +275,7 @@ Internamente usa Git per gestire le modifiche ai file. Quindi il progetto **deve ### annulla condivisione -Annulla la condivisione della sessione corrente. [Scopri di piu](/docs/share#un-sharing). +Annulla la condivisione della sessione corrente. [Scopri di più](/docs/share#un-sharing). ```bash frame="none" /unshare @@ -346,30 +346,40 @@ Opzioni comuni per l'editor includono: Alcuni editor come VS Code devono essere avviati con il flag `--wait`. ::: -Alcuni editor richiedono argomenti da riga di comando per funzionare in modalita bloccante. Il flag `--wait` fa si che il processo dell'editor resti in attesa finche non viene chiuso. +Alcuni editor richiedono argomenti da riga di comando per funzionare in modalità bloccante. Il flag `--wait` fa sì che il processo dell'editor resti in attesa finché non viene chiuso. --- ## Configurazione -Puoi personalizzare il comportamento della TUI tramite il file di config di OpenCode. +Puoi personalizzare il comportamento della TUI tramite `tui.json` (o `tui.jsonc`). -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +Questo è separato da `opencode.json`, che configura il comportamento di server/runtime. + ### Opzioni -- `scroll_acceleration` - Abilita l'accelerazione di scroll in stile macOS per uno scorrimento fluido e naturale. Quando abilitata, la velocita aumenta con gesture rapide e resta precisa con movimenti lenti. **Questa impostazione ha precedenza su `scroll_speed` e lo sovrascrive quando attiva.** -- `scroll_speed` - Controlla la velocita di scorrimento della TUI quando usi i comandi di scroll (minimo: `1`). Default: `3`. **Nota: viene ignorata se `scroll_acceleration.enabled` e impostato a `true`.** +- `theme` - Imposta il tema della UI. [Scopri di più](/docs/themes). +- `keybinds` - Personalizza le scorciatoie da tastiera. [Scopri di più](/docs/keybinds). +- `scroll_acceleration.enabled` - Abilita l'accelerazione di scroll in stile macOS per uno scorrimento fluido e naturale. Quando abilitata, la velocità aumenta con gesture rapide e resta precisa con movimenti lenti. **Questa impostazione ha precedenza su `scroll_speed` e lo sovrascrive quando attiva.** +- `scroll_speed` - Controlla la velocità di scorrimento della TUI quando usi i comandi di scroll (minimo: `0.001`, supporta valori decimali). Default: `3`. **Nota: viene ignorata se `scroll_acceleration.enabled` è impostato a `true`.** +- `diff_style` - Controlla il rendering delle diff. `"auto"` si adatta alla larghezza del terminale, `"stacked"` mostra sempre un layout a colonna singola. + +Usa `OPENCODE_TUI_CONFIG` per caricare un path di configurazione TUI personalizzato. --- diff --git a/packages/web/src/content/docs/it/zen.mdx b/packages/web/src/content/docs/it/zen.mdx index 8ea628aee2..db0434db50 100644 --- a/packages/web/src/content/docs/it/zen.mdx +++ b/packages/web/src/content/docs/it/zen.mdx @@ -55,6 +55,7 @@ Puoi anche accedere ai nostri modelli tramite i seguenti endpoint API. | Modello | ID modello | Endpoint | Pacchetto AI SDK | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -64,22 +65,24 @@ Puoi anche accedere ai nostri modelli tramite i seguenti endpoint API. | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -106,29 +109,34 @@ Supportiamo un modello pay-as-you-go. Qui sotto trovi i prezzi **per 1M token**. | Modello | Input | Output | Lettura in cache | Scrittura in cache | | --------------------------------- | ------ | ------ | ---------------- | ------------------ | | Big Pickle | Gratis | Gratis | Gratis | - | -| MiniMax M2.1 Free | Gratis | Gratis | Gratis | - | +| MiniMax M2.5 Free | Gratis | Gratis | Gratis | - | +| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | - | | MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | -| GLM 4.7 Free | Gratis | Gratis | Gratis | - | +| GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 Free | Gratis | Gratis | Gratis | - | | Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - | +| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Claude Sonnet 4.6 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.6 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4.5 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | -| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - | @@ -147,9 +155,7 @@ Le commissioni della carta di credito vengono ribaltate al costo (4.4% + $0.30 p I modelli gratuiti: -- GLM 4.7 Free e disponibile su OpenCode per un periodo limitato. Il team usa questo tempo per raccogliere feedback e migliorare il modello. -- Kimi K2.5 Free e disponibile su OpenCode per un periodo limitato. Il team usa questo tempo per raccogliere feedback e migliorare il modello. -- MiniMax M2.1 Free e disponibile su OpenCode per un periodo limitato. Il team usa questo tempo per raccogliere feedback e migliorare il modello. +- MiniMax M2.5 Free e disponibile su OpenCode per un periodo limitato. Il team usa questo tempo per raccogliere feedback e migliorare il modello. - Big Pickle e un modello stealth gratuito su OpenCode per un periodo limitato. Il team usa questo tempo per raccogliere feedback e migliorare il modello. Contattaci se hai domande. @@ -177,9 +183,7 @@ Per esempio, se imposti un limite mensile a $20, Zen non usera piu di $20 in un Tutti i nostri modelli sono ospitati negli US. I nostri provider seguono una policy di zero-retention e non usano i tuoi dati per training dei modelli, con le seguenti eccezioni: - Big Pickle: durante il periodo gratuito, i dati raccolti potrebbero essere usati per migliorare il modello. -- GLM 4.7 Free: durante il periodo gratuito, i dati raccolti potrebbero essere usati per migliorare il modello. -- Kimi K2.5 Free: durante il periodo gratuito, i dati raccolti potrebbero essere usati per migliorare il modello. -- MiniMax M2.1 Free: durante il periodo gratuito, i dati raccolti potrebbero essere usati per migliorare il modello. +- MiniMax M2.5 Free: durante il periodo gratuito, i dati raccolti potrebbero essere usati per migliorare il modello. - OpenAI APIs: le richieste vengono conservate per 30 giorni in conformita alle [OpenAI's Data Policies](https://platform.openai.com/docs/guides/your-data). - Anthropic APIs: le richieste vengono conservate per 30 giorni in conformita alle [Anthropic's Data Policies](https://docs.anthropic.com/en/docs/claude-code/data-usage). diff --git a/packages/web/src/content/docs/ja/cli.mdx b/packages/web/src/content/docs/ja/cli.mdx index aeae74731f..dcb411c833 100644 --- a/packages/web/src/content/docs/ja/cli.mdx +++ b/packages/web/src/content/docs/ja/cli.mdx @@ -335,20 +335,20 @@ opencode run --attach http://localhost:4096 "Explain async/await in JavaScript" #### フラグ -| フラグ | ショート | 説明 | -| ------------ | ----------- | ----------------------------------------------------------------------------------------- | -| `--command` | | 実行するコマンド。引数には message を使用します。 | -| `--continue` | `-c` | 最後のセッションを続行 | -| `--session` | | 続行時にセッションをフォーク (`-s` または `--fork` と併用) | -| `--continue` | `--session` | 続行するセッション ID | -| `--share` | | セッションを共有する | -| `--model` | `-m` | プロバイダー/モデルの形式で使用するモデル | -| `--agent` | | 使用するエージェント | -| `--file` | `-f` | メッセージに添付するファイル | -| `--format` | | 形式: デフォルト (フォーマット済み) または json (生の JSON イベント) | -| `--title` | | セッションのタイトル (値が指定されていない場合は、切り詰められたプロンプトが使用されます) | -| `--attach` | | 実行中の opencode サーバー (http://localhost:4096 など) に接続します。 | -| `--port` | | ローカルサーバーのポート (デフォルトはランダムポート) | +| フラグ | ショート | 説明 | +| ------------ | -------- | ----------------------------------------------------------------------------------------- | +| `--command` | | 実行するコマンド。引数には message を使用します。 | +| `--continue` | `-c` | 最後のセッションを続行 | +| `--session` | `-s` | 続行するセッション ID | +| `--fork` | | 続行時にセッションをフォーク (`--continue` または `--session` と併用) | +| `--share` | | セッションを共有する | +| `--model` | `-m` | プロバイダー/モデルの形式で使用するモデル | +| `--agent` | | 使用するエージェント | +| `--file` | `-f` | メッセージに添付するファイル | +| `--format` | | 形式: デフォルト (フォーマット済み) または json (生の JSON イベント) | +| `--title` | | セッションのタイトル (値が指定されていない場合は、切り詰められたプロンプトが使用されます) | +| `--attach` | | 実行中の opencode サーバー (http://localhost:4096 など) に接続します。 | +| `--port` | | ローカルサーバーのポート (デフォルトはランダムポート) | --- diff --git a/packages/web/src/content/docs/ja/config.mdx b/packages/web/src/content/docs/ja/config.mdx index 114336d43c..20e29190da 100644 --- a/packages/web/src/content/docs/ja/config.mdx +++ b/packages/web/src/content/docs/ja/config.mdx @@ -14,10 +14,11 @@ OpenCode は、**JSON** と **JSONC** (コメント付きの JSON) 形式の両 ```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", - // Theme configuration - "theme": "opencode", "model": "anthropic/claude-sonnet-4-5", "autoupdate": true, + "server": { + "port": 4096, + }, } ``` @@ -25,14 +26,15 @@ OpenCode は、**JSON** と **JSONC** (コメント付きの JSON) 形式の両 ## ファイルの場所 -設定をいくつかの異なる場所に配置できます。 -優先順位が異なります。 +設定をいくつかの異なる場所に配置できます。それらは異なる優先順位を持ちます。 :::note -設定ファイルは置き換えられるのではなく、**マージ**されます。設定は、次の構成場所から結合されます。後続の設定は、競合するキーに対してのみ以前の設定をオーバーライドします。すべての設定の競合しない設定は保持されます。 +設定ファイルは置き換えられるのではなく、**マージ**されます。 ::: -たとえば、グローバル設定で `theme: "opencode"` と `autoupdate: true` が設定され、プロジェクト設定で `model: "anthropic/claude-sonnet-4-5"` が設定されている場合、最終的な設定には 3 つの設定がすべて含まれます。 +設定ファイルは結合され、置き換えられません。次の構成場所からの設定が結合されます。競合するキーに対してのみ、後の設定が前の設定を上書きします。すべての構成からの競合しない設定は保持されます。 + +たとえば、グローバル設定で `autoupdate: true` を設定し、プロジェクト設定で `model: "anthropic/claude-sonnet-4-5"` を設定した場合、最終的な構成には両方の設定が含まれます。 --- @@ -93,7 +95,9 @@ OpenCode は、**JSON** と **JSONC** (コメント付きの JSON) 形式の両 ### グローバル -グローバル OpenCode 設定を `~/.config/opencode/opencode.json` に配置します。テーマ、プロバイダー、キーバインドなどのユーザー全体の設定にはグローバル設定を使用します。 +グローバル OpenCode 設定を `~/.config/opencode/opencode.json` に配置します。プロバイダー、モデル、権限などのユーザー全体の設定にはグローバル設定を使用します。 + +TUI 固有の設定には、`~/.config/opencode/tui.json` を使用します。 グローバル設定はリモート組織のデフォルトをオーバーライドします。 @@ -103,6 +107,8 @@ OpenCode は、**JSON** と **JSONC** (コメント付きの JSON) 形式の両 プロジェクトのルートに `opencode.json` を追加します。プロジェクト設定は、標準設定ファイルの中で最も高い優先順位を持ち、グローバル設定とリモート設定の両方をオーバーライドします。 +プロジェクト固有の TUI 設定については、その横に `tui.json` を追加します。 + :::tip プロジェクト固有の設定をプロジェクトのルートに配置します。 ::: @@ -144,7 +150,9 @@ opencode run "Hello world" ## スキーマ -設定ファイルには、[**`opencode.ai/config.json`**](https://opencode.ai/config.json) を使用します。 +サーバー/ランタイム構成スキーマは [**`opencode.ai/config.json`**](https://opencode.ai/config.json) で定義されています。 + +TUI 設定は [**`opencode.ai/tui.json`**](https://opencode.ai/tui.json) を使用します。 エディターはスキーマに基づいて検証し、オートコンプリートできる必要があります。 @@ -152,28 +160,24 @@ opencode run "Hello world" ### TUI -`tui` オプションを使用して TUI 固有の設定を構成できます。 +TUI 固有の設定には、専用の `tui.json` (または `tui.jsonc`) ファイルを使用します。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - }, - "diff_style": "auto" - } + "$schema": "https://opencode.ai/tui.json", + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` -利用可能なオプション: +カスタム TUI 設定ファイルを指定するには、`OPENCODE_TUI_CONFIG` を使用します。 -- `scroll_acceleration.enabled` - macOS スタイルのスクロールアクセラレーションを有効にします。 **`scroll_speed` よりも優先されます。** -- `scroll_speed` - カスタムのスクロール速度乗数 (デフォルト: `3`、最小: `1`)。 `scroll_acceleration.enabled` が `true` の場合は無視されます。 -- `diff_style` - 差分レンダリングを制御します。 `"auto"` はターミナルの幅に適応し、`"stacked"` は常に 1 列を表示します。 +`opencode.json` 内の従来の `theme`、`keybinds`、および `tui` キーは非推奨となり、可能であれば自動的に移行されます。 -[TUI の使用方法の詳細については、こちら](/docs/tui) をご覧ください。 +[TUI の設定の詳細については、こちら](/docs/tui#configure) をご覧ください。 --- @@ -237,7 +241,7 @@ LLM が使用できるツールは、`tools` オプションを通じて管理 } ``` -`small_model` オプションは、タイトル生成などの軽量タスク用に別のモデルを構成します。デフォルトでは、OpenCode は、プロバイダーから安価なモデルが入手可能な場合は、より安価なモデルを使用しようとします。そうでない場合は、メインモデルにフォールバックします。 +`small_model` オプションは、タイトルの生成などの軽量タスク用に個別のモデルを構成します。デフォルトでは、OpenCode は、プロバイダーから安価なモデルが入手可能な場合は、より安価なモデルを使用しようとします。そうでない場合は、メインモデルにフォールバックします。 プロバイダーオプションには、`timeout` および `setCacheKey` を含めることができます。 @@ -258,7 +262,7 @@ LLM が使用できるツールは、`tools` オプションを通じて管理 - `timeout` - リクエストのタイムアウト (ミリ秒単位) (デフォルト: 300000)。無効にするには、`false` に設定します。 - `setCacheKey` - 指定されたプロバイダーに対してキャッシュキーが常に設定されていることを確認します。 -[ローカルモデル](/docs/models#local). [詳細はこちら](/docs/models)。 +[ローカルモデル](/docs/models#local) も設定できます。[詳細はこちら](/docs/models)。 --- @@ -290,21 +294,21 @@ Amazon Bedrock は、AWS 固有の設定をサポートしています。 - `endpoint` - VPC エンドポイントのカスタムエンドポイント URL。これは、AWS 固有の用語を使用した汎用 `baseURL` オプションのエイリアスです。両方を指定した場合は、`endpoint` が優先されます。 :::note -ベアラー トークン (`AWS_BEARER_TOKEN_BEDROCK` または `/connect`) は、プロファイルベースの認証より優先されます。詳細については、「認証優先順位](/docs/providers#authentication-precedence)」を参照してください。 +ベアラー トークン (`AWS_BEARER_TOKEN_BEDROCK` または `/connect`) は、プロファイルベースの認証より優先されます。詳細については、「[認証優先順位](/docs/providers#authentication-precedence)」を参照してください。 ::: -[Amazon Bedrock 設定 ](/docs/providers#amazon-bedrock) の詳細をご覧ください。 +[Amazon Bedrock 設定](/docs/providers#amazon-bedrock) の詳細をご覧ください。 --- ### テーマ -`theme` オプションを使用して、OpenCode 設定で使用するテーマを構成できます。 +UI テーマを `tui.json` で設定します。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "theme": "" + "$schema": "https://opencode.ai/tui.json", + "theme": "tokyonight" } ``` @@ -404,11 +408,11 @@ Amazon Bedrock は、AWS 固有の設定をサポートしています。 ### キーバインド -`keybinds` オプションを使用してキーバインドをカスタマイズできます。 +`tui.json` でキーバインドをカスタマイズします。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": {} } ``` diff --git a/packages/web/src/content/docs/ja/custom-tools.mdx b/packages/web/src/content/docs/ja/custom-tools.mdx index badf50c627..2377fc7730 100644 --- a/packages/web/src/content/docs/ja/custom-tools.mdx +++ b/packages/web/src/content/docs/ja/custom-tools.mdx @@ -79,6 +79,32 @@ export const multiply = tool({ --- +#### 組み込みツールとの名前の衝突 + +カスタムツールはツール名でキー設定されます。カスタムツールが組み込みツールと同じ名前を使用する場合、カスタムツールが優先されます。 + +たとえば、このファイルは組み込みの `bash` ツールを置き換えます。 + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +組み込みツールを意図的に置き換えたい場合を除き、一意の名前を使用することをお勧めします。組み込みツールを無効にしたいがオーバーライドしたくない場合は、[権限](/docs/permissions) を使用してください。 +::: + +--- + ### 引数 引数の型を定義するには、`tool.schema` (つまり [Zod](https://zod.dev)) を使用できます。 diff --git a/packages/web/src/content/docs/ja/formatters.mdx b/packages/web/src/content/docs/ja/formatters.mdx index 26bcbb5de5..8769b9760d 100644 --- a/packages/web/src/content/docs/ja/formatters.mdx +++ b/packages/web/src/content/docs/ja/formatters.mdx @@ -13,31 +13,32 @@ OpenCode には、一般的な言語およびフレームワーク用のいく | Formatter | Extensions | Requirements | | -------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -| gofmt | .go | `gofmt` command available | -| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | `mix` command available | -| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://prettier.io/docs/en/index.html) | `prettier` dependency in `package.json` | -| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://biomejs.dev/) | `biome.json(c)` config file | -| zig | .zig, .zon | `zig` command available | -| clang-format | .c, .cpp, .h, .hpp, .ino, and [more](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` config file | -| ktlint | .kt, .kts | `ktlint` command available | -| ruff | .py, .pyi | `ruff` command available with config | -| rustfmt | .rs | `rustfmt` command available | -| cargofmt | .rs | `cargo fmt` command available | -| uv | .py, .pyi | `uv` command available | -| rubocop | .rb, .rake, .gemspec, .ru | `rubocop` command available | -| standardrb | .rb, .rake, .gemspec, .ru | `standardrb` command available | -| htmlbeautifier | .erb, .html.erb | `htmlbeautifier` command available | | air | .R | `air` command available | +| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://biomejs.dev/) | `biome.json(c)` config file | +| cargofmt | .rs | `cargo fmt` command available | +| clang-format | .c, .cpp, .h, .hpp, .ino, and [more](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` config file | +| cljfmt | .clj, .cljs, .cljc, .edn | `cljfmt` command available | | dart | .dart | `dart` command available | | dfmt | .d | `dfmt` command available | -| ocamlformat | .ml, .mli | `ocamlformat` command available and `.ocamlformat` config file | -| terraform | .tf, .tfvars | `terraform` command available | | gleam | .gleam | `gleam` command available | +| gofmt | .go | `gofmt` command available | +| htmlbeautifier | .erb, .html.erb | `htmlbeautifier` command available | +| ktlint | .kt, .kts | `ktlint` command available | +| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | `mix` command available | | nixfmt | .nix | `nixfmt` command available | -| shfmt | .sh, .bash | `shfmt` command available | -| pint | .php | `laravel/pint` dependency in `composer.json` | -| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | `oxfmt` dependency in `package.json` and an [experimental env variable flag](/docs/cli/#experimental) | +| ocamlformat | .ml, .mli | `ocamlformat` command available and `.ocamlformat` config file | | ormolu | .hs | `ormolu` command available | +| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | `oxfmt` dependency in `package.json` and an [experimental env variable flag](/docs/cli/#experimental) | +| pint | .php | `laravel/pint` dependency in `composer.json` | +| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://prettier.io/docs/en/index.html) | `prettier` dependency in `package.json` | +| rubocop | .rb, .rake, .gemspec, .ru | `rubocop` command available | +| ruff | .py, .pyi | `ruff` command available with config | +| rustfmt | .rs | `rustfmt` command available | +| shfmt | .sh, .bash | `shfmt` command available | +| standardrb | .rb, .rake, .gemspec, .ru | `standardrb` command available | +| terraform | .tf, .tfvars | `terraform` command available | +| uv | .py, .pyi | `uv` command available | +| zig | .zig, .zon | `zig` command available | したがって、プロジェクトの `prettier` に `package.json` が含まれている場合、OpenCode は自動的にそれを使用します。 diff --git a/packages/web/src/content/docs/ja/go.mdx b/packages/web/src/content/docs/ja/go.mdx new file mode 100644 index 0000000000..17ec4acb93 --- /dev/null +++ b/packages/web/src/content/docs/ja/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: オープンコーディングモデル向けの低価格サブスクリプション。 +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Goは、人気のあるオープンコーディングモデルへの信頼性の高いアクセスを提供する、低価格な**月額10ドル**のサブスクリプションです。 + +:::note +OpenCode Goは現在ベータ版です。 +::: + +GoはOpenCodeの他のプロバイダーと同様に機能します。OpenCode Goに登録してAPIキーを取得します。これは**完全にオプション**であり、OpenCodeを使用するために必須ではありません。 + +主に海外ユーザー向けに設計されており、安定したグローバルアクセスのためにモデルは米国、EU、シンガポールでホストされています。 + +--- + +## 背景 + +オープンモデルは非常に高性能になりました。現在では、コーディングタスクにおいてプロプライエタリモデルに近いパフォーマンスを発揮します。また、多くのプロバイダーが競争力のある価格で提供できるため、通常はずっと安価です。 + +しかし、信頼性が高く低遅延なアクセスを得ることは難しい場合があります。プロバイダーによって品質や可用性が異なるためです。 + +:::tip +OpenCodeとうまく連携する厳選されたモデルとプロバイダーをテストしました。 +::: + +これを解決するために、私たちはいくつかのことを行いました。 + +1. 厳選されたオープンモデルをテストし、それらを最適に実行する方法についてチームと話し合いました。 +2. 次に、いくつかのプロバイダーと協力して、これらが正しく提供されていることを確認しました。 +3. 最後に、モデルとプロバイダーの組み合わせをベンチマークし、自信を持って推奨できるリストを作成しました。 + +OpenCode Goでは、これらのモデルに**月額10ドル**でアクセスできます。 + +--- + +## 仕組み + +OpenCode GoはOpenCodeの他のプロバイダーと同様に機能します。 + +1. **OpenCode Zen**にサインインし、Goに登録してAPIキーをコピーします。 +2. TUIで`/connect`コマンドを実行し、`OpenCode Go`を選択してAPIキーを貼り付けます。 +3. TUIで`/models`を実行して、Go経由で利用可能なモデルのリストを確認します。 + +:::note +ワークスペースごとに1人のメンバーのみがOpenCode Goに登録できます。 +::: + +現在のモデルリストには以下が含まれます: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +モデルのリストは、テストや新しいモデルの追加に伴い変更される可能性があります。 + +--- + +## 利用制限 + +OpenCode Goには以下の制限が含まれます: + +- **5時間制限** — 12ドル分の利用 +- **週間制限** — 30ドル分の利用 +- **月間制限** — 60ドル分の利用 + +制限は金額で定義されています。つまり、実際のリクエスト数は使用するモデルによって異なります。MiniMax M2.5のような安価なモデルではより多くのリクエストが可能ですが、GLM-5のような高価なモデルでは少なくなります。 + +下の表は、典型的なGoの使用パターンに基づいた推定リクエスト数を示しています: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ------------------------- | ----- | --------- | ------------ | +| 5時間あたりのリクエスト数 | 1,150 | 1,850 | 30,000 | +| 週間リクエスト数 | 2,880 | 4,630 | 75,000 | +| 月間リクエスト数 | 5,750 | 9,250 | 150,000 | + +推定値は、観測された平均的なリクエストパターンに基づいています: + +- GLM-5 — 1リクエストあたり入力700、キャッシュ52,000、出力150トークン +- Kimi K2.5 — 1リクエストあたり入力870、キャッシュ55,000、出力200トークン +- MiniMax M2.5 — 1リクエストあたり入力300、キャッシュ55,000、出力125トークン + +現在の使用状況は**コンソール**で確認できます。 + +:::tip +利用制限に達した場合でも、無料モデルを引き続き使用できます。 +::: + +利用制限は、初期の使用状況やフィードバックに基づいて変更される可能性があります。 + +--- + +### 価格 + +OpenCode Goは**月額10ドル**のサブスクリプションプランです。以下は**100万トークンあたり**の価格です。 + +| モデル | 入力 | 出力 | キャッシュ読み込み | +| ------------ | ----- | ----- | ------------------ | +| GLM-5 | $1.00 | $3.20 | $0.20 | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | +| MiniMax M2.5 | $0.30 | $1.20 | $0.03 | + +--- + +### 制限を超えた利用 + +Zen残高にクレジットがある場合、コンソールで**残高を使用 (Use balance)**オプションを有効にできます。有効にすると、利用制限に達した後、リクエストをブロックする代わりにZen残高が使用されます。 + +--- + +## エンドポイント + +以下のAPIエンドポイントを通じてGoモデルにアクセスすることもできます。 + +| モデル | モデルID | エンドポイント | AI SDKパッケージ | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +OpenCode設定の[モデルID](/docs/config/#models)は、`opencode-go/`という形式を使用します。たとえば、Kimi K2.5の場合、設定で`opencode-go/kimi-k2.5`を使用します。 + +--- + +## プライバシー + +このプランは主に海外ユーザー向けに設計されており、安定したグローバルアクセスのためにモデルは米国、EU、シンガポールでホストされています。 + +ご質問がある場合はお問い合わせください。 + +--- + +## 目標 + +OpenCode Goを作成した目的は以下の通りです: + +1. 低価格のサブスクリプションで、より多くの人々がAIコーディングに**アクセス**できるようにすること。 +2. 最高のオープンコーディングモデルへの**信頼性の高い**アクセスを提供すること。 +3. コーディングエージェントでの使用向けに**テストおよびベンチマーク**されたモデルを厳選すること。 +4. OpenCodeで他のプロバイダーも使用できるようにすることで、**ロックインを排除**すること。 diff --git a/packages/web/src/content/docs/ja/keybinds.mdx b/packages/web/src/content/docs/ja/keybinds.mdx index 66466a7f72..09a3b0d7cb 100644 --- a/packages/web/src/content/docs/ja/keybinds.mdx +++ b/packages/web/src/content/docs/ja/keybinds.mdx @@ -3,11 +3,11 @@ title: キーバインド description: キーバインドをカスタマイズします。 --- -OpenCode には、OpenCode 設定を通じてカスタマイズできるキーバインドのリストがあります。 +OpenCode には、`tui.json` を通じてカスタマイズできるキーバインドのリストがあります。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -117,11 +117,11 @@ OpenCode は、ほとんどのキーバインドに `leader` キーを使用し ## キーバインドを無効にする -キーバインドを無効にするには、値「none」を指定してキーを構成に追加します。 +キーバインドを無効にするには、値「none」を指定してキーを `tui.json` に追加します。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/ja/lsp.mdx b/packages/web/src/content/docs/ja/lsp.mdx index 7b42c37332..948e743503 100644 --- a/packages/web/src/content/docs/ja/lsp.mdx +++ b/packages/web/src/content/docs/ja/lsp.mdx @@ -27,6 +27,7 @@ OpenCode には、一般的な言語用のいくつかの組み込み LSP サー | gopls | .go | `go` command available | | hls | .hs, .lhs | `haskell-language-server-wrapper` command available | | jdtls | .java | `Java SDK (version 21+)` installed | +| julials | .jl | `julia` and `LanguageServer.jl` installed | | kotlin-ls | .kt, .kts | Auto-installs for Kotlin projects | | lua-ls | .lua | Auto-installs for Lua projects | | nixd | .nix | `nixd` command available | diff --git a/packages/web/src/content/docs/ja/mcp-servers.mdx b/packages/web/src/content/docs/ja/mcp-servers.mdx index a4b2485337..3ac9edc811 100644 --- a/packages/web/src/content/docs/ja/mcp-servers.mdx +++ b/packages/web/src/content/docs/ja/mcp-servers.mdx @@ -16,7 +16,8 @@ MCP サーバーを使用すると、コンテキストが追加されます。 :::tip MCP サーバーはコンテキストに追加されるため、どのサーバーを有効にするかには注意してください。 ::: -特定の MCP サーバーは、大量のトークンを追加する傾向があり、コンテキスト制限を簡単に超える可能性があります。 + +特定の MCP サーバー (GitHub MCP サーバーなど) は、大量のトークンを追加する傾向があり、コンテキスト制限を簡単に超える可能性があります。 --- @@ -157,7 +158,7 @@ use the mcp_everything tool to add the number 3 and 4 | `url` | 文字列 | Y | リモート MCP サーバーの URL。 | | `enabled` | ブール値 | | 起動時に MCP サーバーを有効または無効にします。 | | `headers` | オブジェクト | | リクエストとともに送信するヘッダー。 | -| `oauth` | オブジェクト | | OAuth 認証設定。以下の「OAuth](#oauth)」セクションを参照してください。 | +| `oauth` | オブジェクト | | OAuth 認証設定。以下の「[OAuth](#oauth)」セクションを参照してください。 | | `timeout` | 数値 | | MCP サーバーからツールを取得する際のタイムアウト (ミリ秒)。デフォルトは 5000 (5 秒) です。 | --- @@ -391,6 +392,8 @@ MCP サーバーツールはサーバー名をプレフィックスとして登 ::: +--- + ## 例 以下に、一般的な MCP サーバーの例をいくつか示します。他のサーバーを文書化したい場合は、PR を送信できます。 @@ -506,471 +509,3 @@ What's the right way to set a custom domain in an SST Astro component? use the g ```md title="AGENTS.md" If you are unsure how to do something, use `gh_grep` to search code examples from GitHub. ``` - -`enabled` を `false` に設定してサーバーを無効にすることもできます。これは、サーバーを構成から削除せずに一時的に無効にする場合に便利です。 - ---- - -### リモートのデフォルトを上書きする - -組織は、`.well-known/opencode` エンドポイント経由でデフォルトの MCP サーバーを提供できます。これらのサーバーはデフォルトで無効になっている場合があり、ユーザーは必要なサーバーにオプトインできます。 - -組織のリモート構成から特定のサーバーを有効にするには、`enabled: true` を使用してローカル構成に追加します。 - -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "jira": { - "type": "remote", - "url": "https://jira.example.com/mcp", - "enabled": true - } - } -} -``` - -ローカルの設定値はリモートのデフォルト値をオーバーライドします。詳細については、「config precedence](/docs/config#precedence-order)」を参照してください。 - ---- - -## ローカル - -MCP オブジェクト内の `type` から `"local"` を使用してローカル MCP サーバーを追加します。 - -```jsonc title="opencode.jsonc" {15} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-local-mcp-server": { - "type": "local", - // Or ["bun", "x", "my-mcp-command"] - "command": ["npx", "-y", "my-mcp-command"], - "enabled": true, - "environment": { - "MY_ENV_VAR": "my_env_var_value", - }, - }, - }, -} -``` - -このコマンドは、ローカル MCP サーバーの起動方法を示します。環境変数のリストを渡すこともできます。 - -たとえば、テスト [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) MCP サーバー] を追加する方法は次のとおりです。 - -```jsonc title="opencode.jsonc" -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "mcp_everything": { - "type": "local", - "command": ["npx", "-y", "@modelcontextprotocol/server-everything"], - }, - }, -} -``` - -これを使用するには、プロンプトに `use the mcp_everything tool` を追加します。 - -```txt "mcp_everything" -use the mcp_everything tool to add the number 3 and 4 -``` - ---- - -#### オプション - -ここでは、ローカル MCP サーバーを構成するためのすべてのオプションを示します。 - -| オプション | タイプ | 必須 | 説明 | -| ------------- | ------------ | ---- | ------------------------------------------------------------------------------------------ | -| `type` | 文字列 | Y | MCP サーバー接続のタイプは、`"local"` である必要があります。 | -| `command` | 配列 | Y | MCP サーバーを実行するためのコマンドと引数。 | -| `environment` | オブジェクト | | サーバーの実行時に設定する環境変数。 | -| `enabled` | ブール値 | | 起動時に MCP サーバーを有効または無効にします。 | -| `timeout` | 番号 | | MCP サーバーからツールを取得する際のタイムアウト (ミリ秒)。デフォルトは 5000 (5 秒) です。 | - ---- - -## リモート - -`type` を `"remote"` に設定して、リモート MCP サーバーを追加します。 - -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-remote-mcp": { - "type": "remote", - "url": "https://my-mcp-server.com", - "enabled": true, - "headers": { - "Authorization": "Bearer MY_API_KEY" - } - } - } -} -``` - -`url` はリモート MCP サーバーの URL で、`headers` オプションを使用するとヘッダーのリストを渡すことができます。 - ---- - -#### オプション - -| オプション | タイプ | 必須 | 説明 | -| ---------- | ------------ | ---- | ------------------------------------------------------------------------------------------ | -| `type` | 文字列 | Y | MCP サーバー接続のタイプは、`"remote"` である必要があります。 | -| `url` | 文字列 | Y | リモート MCP サーバーの URL。 | -| `enabled` | ブール値 | | 起動時に MCP サーバーを有効または無効にします。 | -| `headers` | オブジェクト | | リクエストとともに送信するヘッダー。 | -| `oauth` | オブジェクト | | OAuth認証構成。以下の「OAuth](#oauth)」セクションを参照してください。 | -| `timeout` | 番号 | | MCP サーバーからツールを取得する際のタイムアウト (ミリ秒)。デフォルトは 5000 (5 秒) です。 | - ---- - -## OAuth - -OpenCode は、リモート MCP サーバーの OAuth 認証を自動的に処理します。サーバーが認証を必要とする場合、OpenCode は次のことを行います。 - -1. 401 応答を検出し、OAuth フローを開始します。 -2. サーバーでサポートされている場合は **動的クライアント登録 (RFC 7591)** を使用します -3. 今後のリクエストに備えてトークンを安全に保管する - ---- - -### 自動 - -ほとんどの OAuth 対応 MCP サーバーでは、特別な構成は必要ありません。リモートサーバーを設定するだけです。 - -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-oauth-server": { - "type": "remote", - "url": "https://mcp.example.com/mcp" - } - } -} -``` - -サーバーが認証を必要とする場合、OpenCode を初めて使用しようとすると、認証を求めるプロンプトが表示されます。そうでない場合は、`opencode mcp auth ` を使用して flow](#authenticating) を手動でトリガーできます。 - ---- - -### 事前登録済み - -MCP サーバープロバイダーからクライアント認証情報を取得している場合は、それらを構成できます。 - -```json title="opencode.json" {7-11} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-oauth-server": { - "type": "remote", - "url": "https://mcp.example.com/mcp", - "oauth": { - "clientId": "{env:MY_MCP_CLIENT_ID}", - "clientSecret": "{env:MY_MCP_CLIENT_SECRET}", - "scope": "tools:read tools:execute" - } - } - } -} -``` - ---- - -### 認証中 - -手動で認証をトリガーしたり、資格情報を管理したりできます。 - -特定の MCP サーバーで認証します。 - -```bash -opencode mcp auth my-oauth-server -``` - -すべての MCP サーバーとその認証ステータスをリストします。 - -```bash -opencode mcp list -``` - -保存されている認証情報を削除します。 - -```bash -opencode mcp logout my-oauth-server -``` - -`mcp auth` コマンドは、認証のためにブラウザを開きます。承認後、OpenCode はトークンを `~/.local/share/opencode/mcp-auth.json` に安全に保存します。 - ---- - -#### OAuthの無効化 - -サーバー (代わりに API キーを使用するサーバーなど) の自動 OAuth を無効にする場合は、`oauth` を `false` に設定します。 - -```json title="opencode.json" {7} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-api-key-server": { - "type": "remote", - "url": "https://mcp.example.com/mcp", - "oauth": false, - "headers": { - "Authorization": "Bearer {env:MY_API_KEY}" - } - } - } -} -``` - ---- - -#### OAuth オプション - -| オプション | タイプ | 説明 | -| -------------- | --------------- | -------------------------------------------------------------------------------- | -| `oauth` | Object \| false | OAuth config object, or `false` to disable OAuth auto-detection. | -| `clientId` | String | OAuth client ID. If not provided, dynamic client registration will be attempted. | -| `clientSecret` | String | OAuth client secret, if required by the authorization server. | -| `scope` | String | OAuth scopes to request during authorization. | - -#### デバッグ - -リモート MCP サーバーが認証に失敗した場合は、次の方法で問題を診断できます。 - -```bash -# View auth status for all OAuth-capable servers -opencode mcp auth list - -# Debug connection and OAuth flow for a specific server -opencode mcp debug my-oauth-server -``` - -`mcp debug` コマンドは、現在の認証ステータスを表示し、HTTP 接続をテストし、OAuth 検出フローを試行します。 - ---- - -## 管理 - -MCP は、組み込みツールと並んで、OpenCode のツールとして利用できます。したがって、他のツールと同様に、OpenCode config を通じてそれらを管理できます。 - ---- - -### グローバル - -これは、それらをグローバルに有効または無効にできることを意味します。 - -```json title="opencode.json" {14} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-mcp-foo": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-foo"] - }, - "my-mcp-bar": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-bar"] - } - }, - "tools": { - "my-mcp-foo": false - } -} -``` - -グロブ パターンを使用して、一致するすべての MCP を無効にすることもできます。 - -```json title="opencode.json" {14} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-mcp-foo": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-foo"] - }, - "my-mcp-bar": { - "type": "local", - "command": ["bun", "x", "my-mcp-command-bar"] - } - }, - "tools": { - "my-mcp*": false - } -} -``` - -ここでは、グロブ パターン `my-mcp*` を使用して、すべての MCP を無効にしています。 - ---- - -### エージェントごと - -多数の MCP サーバーがある場合は、エージェントごとにのみ有効にし、グローバルに無効にすることができます。これを行うには: - -1. ツールとしてグローバルに無効にします。 -2. [エージェント config](/docs/agents#tools) で、MCP サーバーをツールとして有効にします。 - -```json title="opencode.json" {11, 14-18} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "my-mcp": { - "type": "local", - "command": ["bun", "x", "my-mcp-command"], - "enabled": true - } - }, - "tools": { - "my-mcp*": false - }, - "agent": { - "my-agent": { - "tools": { - "my-mcp*": true - } - } - } -} -``` - ---- - -#### グロブパターン - -グロブ パターンでは、単純な正規表現のグロブ パターンを使用します。 - -- `*` は 0 個以上の任意の文字に一致します (例: `"my-mcp*"` は `my-mcp_search`、`my-mcp_list` などに一致します)。 -- `?` は 1 つの文字に正確に一致します -- 他のすべての文字は文字通り一致します - -:::note -MCP サーバー ツールはサーバー名をプレフィックスとして登録されているため、サーバーのすべてのツールを無効にするには、次のコマンドを使用するだけです。 - -``` -"mymcpservername_*": false -``` - -::: - -## 例 - -以下に、一般的な MCP サーバーの例をいくつか示します。他のサーバーを文書化したい場合は、PR を送信できます。 - ---- - -### Sentry - -[Sentry MCP サーバー ](https://mcp.sentry.dev) を追加して、Sentry プロジェクトや問題と対話します。 - -```json title="opencode.json" {4-8} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "sentry": { - "type": "remote", - "url": "https://mcp.sentry.dev/mcp", - "oauth": {} - } - } -} -``` - -構成を追加した後、Sentry で認証します。 - -```bash -opencode mcp auth sentry -``` - -これにより、ブラウザ ウィンドウが開き、OAuth フローが完了し、OpenCode が Sentry アカウントに接続されます。 - -認証が完了すると、プロンプトで Sentry ツールを使用して、問題、プロジェクト、エラー データをクエリできるようになります。 - -```txt "use sentry" -Show me the latest unresolved issues in my project. use sentry -``` - ---- - -### Context7 - -ドキュメントを検索するために [Context7 MCP server](https://github.com/upstash/context7) を追加します。 - -```json title="opencode.json" {4-7} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "context7": { - "type": "remote", - "url": "https://mcp.context7.com/mcp" - } - } -} -``` - -無料アカウントにサインアップしている場合は、API キーを使用して、より高いレート制限を取得できます。 - -```json title="opencode.json" {7-9} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "context7": { - "type": "remote", - "url": "https://mcp.context7.com/mcp", - "headers": { - "CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}" - } - } - } -} -``` - -ここでは、`CONTEXT7_API_KEY` 環境変数が設定されていることを前提としています。 - -Context7 MCP サーバーを使用するには、プロンプトに `use context7` を追加します。 - -```txt "use context7" -Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7 -``` - -あるいは、次のようなものを [AGENTS.md](/docs/rules/). - -```md title="AGENTS.md" -When you need to search docs, use `context7` tools. -``` - ---- - -### Grep by Vercel - -GitHub 上のコード スニペットを検索するには、[Grep by Vercel](https://grep.app) MCP サーバーを追加します。 - -```json title="opencode.json" {4-7} -{ - "$schema": "https://opencode.ai/config.json", - "mcp": { - "gh_grep": { - "type": "remote", - "url": "https://mcp.grep.app" - } - } -} -``` - -MCP サーバーに `gh_grep` という名前を付けたので、プロンプトに `use the gh_grep tool` を追加して、エージェントにそれを使用させることができます。 - -```txt "use the gh_grep tool" -What's the right way to set a custom domain in an SST Astro component? use the gh_grep tool -``` - -あるいは、次のようなものを [AGENTS.md](/docs/rules/). - -```md title="AGENTS.md" -If you are unsure how to do something, use `gh_grep` to search code examples from GitHub. -``` diff --git a/packages/web/src/content/docs/ja/plugins.mdx b/packages/web/src/content/docs/ja/plugins.mdx index 39fc1dda21..06a0dca9ad 100644 --- a/packages/web/src/content/docs/ja/plugins.mdx +++ b/packages/web/src/content/docs/ja/plugins.mdx @@ -235,11 +235,87 @@ export const NotificationPlugin = async ({ project, client, $, directory, worktr macOS 上で AppleScript を実行するために `osascript` を使用しています。ここでは通知を送信するために使用しています。 :::note -OpenCode デスクトップアプリを使用している場合は、応答の準備ができたとき、またはセッションエラーが発生したときにシステム通知を自動的に送信できます。 +組み込みツールと同じ名前のプラグインツールを使用すると、プラグインツールが優先されます。 ::: --- +### ロギング + +構造化ログには `console.log` の代わりに `client.app.log()` を使用します。 + +```ts title=".opencode/plugins/my-plugin.ts" +export const MyPlugin = async ({ client }) => { + await client.app.log({ + body: { + service: "my-plugin", + level: "info", + message: "Plugin initialized", + extra: { foo: "bar" }, + }, + }) +} +``` + +レベル: `debug`、`info`、`warn`、`error`。詳細については、[SDK ドキュメント](https://opencode.ai/docs/sdk) を参照してください。 + +--- + +### 圧縮フック + +セッションが圧縮されたときに含まれるコンテキストをカスタマイズします。 + +```ts title=".opencode/plugins/compaction.ts" +import type { Plugin } from "@opencode-ai/plugin" + +export const CompactionPlugin: Plugin = async (ctx) => { + return { + "experimental.session.compacting": async (input, output) => { + // Inject additional context into the compaction prompt + output.context.push(` +## Custom Context + +Include any state that should persist across compaction: +- Current task status +- Important decisions made +- Files being actively worked on +`) + }, + } +} +``` + +`experimental.session.compacting` フックは、LLM が継続概要を生成する前に起動します。これを使用して、デフォルトの圧縮プロンプトでは見逃されるドメイン固有のコンテキストを挿入します。 + +`output.prompt` を設定することで、圧縮プロンプトを完全に置き換えることもできます。 + +```ts title=".opencode/plugins/custom-compaction.ts" +import type { Plugin } from "@opencode-ai/plugin" + +export const CustomCompactionPlugin: Plugin = async (ctx) => { + return { + "experimental.session.compacting": async (input, output) => { + // Replace the entire compaction prompt + output.prompt = ` +You are generating a continuation prompt for a multi-agent swarm session. + +Summarize: +1. The current task and its status +2. Which files are being modified and by whom +3. Any blockers or dependencies between agents +4. The next steps to complete the work + +Format as a structured prompt that a new agent can use to resume work. +` + }, + } +} +``` + +`output.prompt` を設定すると、デフォルトの圧縮プロンプトが完全に置き換えられます。この場合、`output.context` 配列は無視されます。 + +--- + ### .env の保護 OpenCode が `.env` ファイルを読み取らないようにします。 diff --git a/packages/web/src/content/docs/ja/providers.mdx b/packages/web/src/content/docs/ja/providers.mdx index 2602f8ef22..388dc8e41d 100644 --- a/packages/web/src/content/docs/ja/providers.mdx +++ b/packages/web/src/content/docs/ja/providers.mdx @@ -57,7 +57,38 @@ OpenCode で適切に動作することがテストおよび検証されてい 初めての方は、OpenCode Zen から始めることをお勧めします。 ::: -1. TUI で `/connect` コマンドを実行し、opencode を選択して、[opencode.ai/auth](https://opencode.ai/auth) で認証します。 +1. TUI で `/connect` コマンドを実行し、`OpenCode Zen` を選択して、[opencode.ai/zen](https://opencode.ai/zen) にアクセスします。 + + ```txt + /connect + ``` + +2. サインインし、お支払いの詳細を追加し、API キーをコピーします。 + +3. API キーを貼り付けます。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. TUI で `/models` を実行すると、推奨されるモデルのリストが表示されます。 + + ```txt + /models + ``` + +これは OpenCode の他のプロバイダーと同様に機能し、使用は完全にオプションです。 + +--- + +## OpenCode Go + +OpenCode Go は、OpenCode チームによって提供される、人気のあるオープンコーディングモデルへの信頼性の高いアクセスを提供する低コストのサブスクリプションプランです。これらは OpenCode でうまく機能することがテストおよび検証されています。 + +1. TUI で `/connect` コマンドを実行し、`OpenCode Go` を選択して、[opencode.ai/zen](https://opencode.ai/zen) にアクセスします。 ```txt /connect @@ -126,105 +157,111 @@ OpenCode で適切に動作することがテストおよび検証されてい OpenCode で Amazon Bedrock を使用するには: -1. Amazon Bedrock コンソールの **モデルカタログ** に移動してリクエストします。 - 必要なモデルにアクセスします。 +1. Amazon Bedrock コンソールの **モデルカタログ** に移動し、必要なモデルへのアクセスをリクエストします。 -:::tip -Amazon Bedrock で必要なモデルにアクセスできる必要があります。 -::: + :::tip + Amazon Bedrock で必要なモデルにアクセスできる必要があります。 + ::: -2. **次のいずれかの方法を使用して認証を構成します**。 +2. **次のいずれかの方法を使用して認証を構成します**: + + *** #### 環境変数 (クイックスタート) -opencode の実行中に次の環境変数のいずれかを設定します。 + opencode の実行中に次の環境変数のいずれかを設定します。 -```bash - # Option 1: Using AWS access keys + ```bash + # オプション 1: AWS アクセスキーの使用 AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode - # Option 2: Using named AWS profile + # オプション 2: 名前付き AWS プロファイルの使用 AWS_PROFILE=my-profile opencode - # Option 3: Using Bedrock bearer token + # オプション 3: Bedrock ベアラートークンの使用 AWS_BEARER_TOKEN_BEDROCK=XXX opencode -``` + ``` -または、それらを bash プロファイルに追加します。 + または、それらを bash プロファイルに追加します。 -```bash title="~/.bash_profile" + ```bash title="~/.bash_profile" export AWS_PROFILE=my-dev-profile export AWS_REGION=us-east-1 -``` + ``` -#### 設定ファイル (推奨) + *** -プロジェクト固有の設定または永続的な設定の場合は、`opencode.json` を使用します。 + #### 設定ファイル (推奨) -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "provider": { - "amazon-bedrock": { - "options": { - "region": "us-east-1", - "profile": "my-aws-profile" - } - } - } -} -``` + プロジェクト固有の設定または永続的な設定の場合は、`opencode.json` を使用します。 -**利用可能なオプション:** + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile" + } + } + } + } + ``` -- `region` - AWS リージョン (例: `us-east-1`、`eu-west-1`) -- `profile` - `~/.aws/credentials` からの AWS 名前付きプロファイル -- `endpoint` - VPC エンドポイントのカスタムエンドポイント URL (汎用 `baseURL` オプションのエイリアス) + **利用可能なオプション:** + - `region` - AWS リージョン (例: `us-east-1`、`eu-west-1`) + - `profile` - `~/.aws/credentials` からの AWS 名前付きプロファイル + - `endpoint` - VPC エンドポイントのカスタムエンドポイント URL (汎用 `baseURL` オプションのエイリアス) -:::tip -設定ファイルのオプションは環境変数より優先されます。 -::: + :::tip + 設定ファイルのオプションは環境変数より優先されます。 + ::: -#### 上級: VPC エンドポイント + *** -Bedrock の VPC エンドポイントを使用している場合: + #### 上級: VPC エンドポイント -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "provider": { - "amazon-bedrock": { - "options": { - "region": "us-east-1", - "profile": "production", - "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" - } - } - } -} -``` + Bedrock の VPC エンドポイントを使用している場合: -:::note -`endpoint` オプションは、AWS 固有の用語を使用した汎用の `baseURL` オプションのエイリアスです。 `endpoint` と `baseURL` の両方が指定された場合は、`endpoint` が優先されます。 -::: + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "production", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } + } + ``` -#### 認証方法 + :::note + `endpoint` オプションは、AWS 固有の用語を使用した汎用の `baseURL` オプションのエイリアスです。 `endpoint` と `baseURL` の両方が指定された場合は、`endpoint` が優先されます。 + ::: -- **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: IAM ユーザーを作成し、AWS コンソールでアクセスキーを生成します。 -- **`AWS_PROFILE`**: `~/.aws/credentials` の名前付きプロファイルを使用します。最初に `aws configure --profile my-profile` または `aws sso login` を設定します -- **`AWS_BEARER_TOKEN_BEDROCK`**: Amazon Bedrock コンソールから長期 API キーを生成します -- **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: EKS IRSA (サービスアカウントの IAM ロール) または OIDC フェデレーションを備えた他の Kubernetes 環境の場合。これらの環境変数は、サービスアカウントアノテーションを使用するときに Kubernetes によって自動的に挿入されます。 + *** -#### 認証の優先順位 + #### 認証方法 + - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: IAM ユーザーを作成し、AWS コンソールでアクセスキーを生成します + - **`AWS_PROFILE`**: `~/.aws/credentials` の名前付きプロファイルを使用します。最初に `aws configure --profile my-profile` または `aws sso login` を設定します + - **`AWS_BEARER_TOKEN_BEDROCK`**: Amazon Bedrock コンソールから長期 API キーを生成します + - **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: EKS IRSA (サービスアカウントの IAM ロール) または OIDC フェデレーションを備えた他の Kubernetes 環境の場合。これらの環境変数は、サービスアカウントアノテーションを使用するときに Kubernetes によって自動的に挿入されます。 -Amazon Bedrock は次の認証優先度を使用します。 + *** -1. **ベアラー トークン** - `AWS_BEARER_TOKEN_BEDROCK` 環境変数または `/connect` コマンドからのトークン -2. **AWS 認証情報チェーン** - プロファイル、アクセスキー、共有認証情報、IAM ロール、Web ID トークン (EKS IRSA)、インスタンスメタデータ + #### 認証の優先順位 -:::note -ベアラー トークンが (`/connect` または `AWS_BEARER_TOKEN_BEDROCK` 経由で) 設定されると、設定されたプロファイルを含むすべての AWS 認証情報方法よりも優先されます。 -::: + Amazon Bedrock は次の認証優先度を使用します。 + 1. **ベアラー トークン** - `AWS_BEARER_TOKEN_BEDROCK` 環境変数または `/connect` コマンドからのトークン + 2. **AWS 認証情報チェーン** - プロファイル、アクセスキー、共有認証情報、IAM ロール、Web ID トークン (EKS IRSA)、インスタンスメタデータ + + :::note + ベアラー トークンが (`/connect` または `AWS_BEARER_TOKEN_BEDROCK` 経由で) 設定されると、設定されたプロファイルを含むすべての AWS 認証情報方法よりも優先されます。 + ::: 3. `/models` コマンドを実行して、必要なモデルを選択します。 @@ -234,6 +271,7 @@ Amazon Bedrock は次の認証優先度を使用します。 :::note カスタム推論プロファイルの場合、キーでモデルとプロバイダー名を使用し、`id` プロパティを arn に設定します。これにより、正しいキャッシュが保証されます。 +::: ```json title="opencode.json" { @@ -251,8 +289,6 @@ Amazon Bedrock は次の認証優先度を使用します。 } ``` -::: - --- ### Anthropic @@ -672,9 +708,42 @@ GitLab Duo は、GitLab の Anthropic プロキシを介したネイティブツ 6. `/models` コマンドを実行して、利用可能なモデルを確認します。 - ```txt - /models - ``` +```txt +/models +``` + +--- + +### STACKIT + +STACKIT AI Model Serving は、Llama、Mistral、Qwen などの LLM に焦点を当て、ヨーロッパのインフラストラクチャでの最大限のデータ主権を備えた、AI モデル用の完全に管理された主権ホスティング環境を提供します。 + +1. [STACKIT Portal](https://portal.stackit.cloud) に移動し、**AI Model Serving** に移動して、プロジェクトの認証トークンを作成します。 + + :::tip + 認証トークンを作成する前に、STACKIT 顧客アカウント、ユーザーアカウント、およびプロジェクトが必要です。 + ::: + +2. `/connect` コマンドを実行し、**STACKIT** を検索します。 + + ```txt + /connect + ``` + +3. STACKIT AI Model Serving 認証トークンを入力します。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` コマンドを実行して、_Qwen3-VL 235B_ や _Llama 3.3 70B_ などの利用可能なモデルから選択します。 + + ```txt + /models + ``` 3 つの Claude ベースのモデルが利用可能です。 diff --git a/packages/web/src/content/docs/ja/sdk.mdx b/packages/web/src/content/docs/ja/sdk.mdx index ee5fd3645a..5afaeb4a13 100644 --- a/packages/web/src/content/docs/ja/sdk.mdx +++ b/packages/web/src/content/docs/ja/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## 構造化出力 + +`format` を JSON スキーマで指定することで、モデルから構造化された JSON 出力をリクエストできます。モデルは `StructuredOutput` ツールを使用して、スキーマに一致する検証済み JSON を返します。 + +### 基本的な使用法 + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Access the structured output +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### 出力フォーマットの種類 + +| タイプ | 説明 | +| ------------- | ---------------------------------------------------- | +| `text` | デフォルト。標準テキスト応答 (構造化出力なし) | +| `json_schema` | 提供されたスキーマに一致する検証済み JSON を返します | + +### JSON スキーマフォーマット + +`type: 'json_schema'` を使用する場合は、以下を指定します: + +| フィールド | タイプ | 説明 | +| ------------ | --------------- | -------------------------------------------------- | +| `type` | `'json_schema'` | 必須。JSON スキーマモードを指定します | +| `schema` | `object` | 必須。出力構造を定義する JSON スキーマオブジェクト | +| `retryCount` | `number` | オプション。検証の再試行回数 (デフォルト: 2) | + +### エラー処理 + +すべての再試行後にモデルが有効な構造化出力を生成できない場合、応答には `StructuredOutputError` が含まれます: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### ベストプラクティス + +1. **明確な説明を提供する**: モデルが抽出するデータを理解できるように、スキーマプロパティに明確な説明を提供します +2. **`required` を使用する**: 存在する必要があるフィールドを指定します +3. **スキーマを焦点を絞ったものにする**: 複雑なネストされたスキーマは、モデルが正しく入力するのが難しい場合があります +4. **適切な `retryCount` を設定する**: 複雑なスキーマの場合は増やし、単純なスキーマの場合は減らします + +--- + ## API SDK は、型安全なクライアントを通じてすべてのサーバー API を公開します。 @@ -226,27 +298,27 @@ const { providers, default: defaults } = await client.config.providers() ### Sessions -| メソッド | 説明 | 詳細 | -| ---------------------------------------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `session.list()` | セッションをリストする | 戻り値 Session[] | -| `session.get({ path })` | セッションを取得 | 戻り値 Session | -| `session.children({ path })` | 子セッションをリストする | 戻り値 Session[] | -| `session.create({ body })` | セッションの作成 | 戻り値 Session | -| `session.delete({ path })` | セッションを削除 | 戻り値 `boolean` | -| `session.update({ path, body })` | セッションのプロパティを更新する | 戻り値 Session | -| `session.init({ path, body })` | アプリを分析して `AGENTS.md` を作成する | 戻り値 `boolean` | -| `session.abort({ path })` | 実行中のセッションを中止する | 戻り値 `boolean` | -| `session.share({ path })` | セッションを共有する | 戻り値 Session | -| `session.unshare({ path })` | セッションの共有を解除 | 戻り値 Session | -| `session.summarize({ path, body })` | セッションを要約する | 戻り値 `boolean` | -| `session.messages({ path })` | セッション内のメッセージをリストする | 戻り値 `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ path })` | メッセージの詳細を取得する | 戻り値 `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | プロンプトメッセージを送信する | `body.noReply: true` は UserMessage (コンテキストのみ) を返します。デフォルトでは、AI 応答を含む AssistantMessage を返します。 | -| `session.command({ path, body })` | コマンドをセッションに送信 | 戻り値 `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | シェルコマンドを実行する | 戻り値 AssistantMessage | -| `session.revert({ path, body })` | メッセージを元に戻す | 戻り値 Session | -| `session.unrevert({ path })` | 元に戻したメッセージを復元する | 戻り値 Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | 許可リクエストに応答する | 戻り値 `boolean` | +| メソッド | 説明 | 詳細 | +| ---------------------------------------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | セッションをリストする | 戻り値 Session[] | +| `session.get({ path })` | セッションを取得 | 戻り値 Session | +| `session.children({ path })` | 子セッションをリストする | 戻り値 Session[] | +| `session.create({ body })` | セッションの作成 | 戻り値 Session | +| `session.delete({ path })` | セッションを削除 | 戻り値 `boolean` | +| `session.update({ path, body })` | セッションのプロパティを更新する | 戻り値 Session | +| `session.init({ path, body })` | アプリを分析して `AGENTS.md` を作成する | 戻り値 `boolean` | +| `session.abort({ path })` | 実行中のセッションを中止する | 戻り値 `boolean` | +| `session.share({ path })` | セッションを共有する | 戻り値 Session | +| `session.unshare({ path })` | セッションの共有を解除 | 戻り値 Session | +| `session.summarize({ path, body })` | セッションを要約する | 戻り値 `boolean` | +| `session.messages({ path })` | セッション内のメッセージをリストする | 戻り値 `{ info: `Message`, parts: `Part[]`}[]` | +| `session.message({ path })` | メッセージの詳細を取得する | 戻り値 `{ info: `Message`, parts: `Part[]`}` | +| `session.prompt({ path, body })` | プロンプトメッセージを送信する | `body.noReply: true` は UserMessage (コンテキストのみ) を返します。デフォルトでは、AI 応答を含む AssistantMessage を返します。[構造化出力](#構造化出力) のための `body.outputFormat` をサポートします。 | +| `session.command({ path, body })` | コマンドをセッションに送信 | 戻り値 `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `session.shell({ path, body })` | シェルコマンドを実行する | 戻り値 AssistantMessage | +| `session.revert({ path, body })` | メッセージを元に戻す | 戻り値 Session | +| `session.unrevert({ path })` | 元に戻したメッセージを復元する | 戻り値 Session | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | 許可リクエストに応答する | 戻り値 `boolean` | --- diff --git a/packages/web/src/content/docs/ja/themes.mdx b/packages/web/src/content/docs/ja/themes.mdx index dd76651d6a..1e4bf42180 100644 --- a/packages/web/src/content/docs/ja/themes.mdx +++ b/packages/web/src/content/docs/ja/themes.mdx @@ -61,11 +61,11 @@ OpenCode にはいくつかの組み込みテーマが付属しています。 ## テーマの使用 -テーマを選択するには、`/theme` コマンドでテーマ選択を表示します。または、[config](/docs/config) で設定します。 +テーマを選択するには、`/theme` コマンドでテーマ選択を表示します。または、`tui.json` で指定することもできます。 -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` diff --git a/packages/web/src/content/docs/ja/tui.mdx b/packages/web/src/content/docs/ja/tui.mdx index 36c94fffcf..0049c7b014 100644 --- a/packages/web/src/content/docs/ja/tui.mdx +++ b/packages/web/src/content/docs/ja/tui.mdx @@ -349,24 +349,34 @@ VS Code などの一部のエディターは、`--wait` フラグを使用して ## 設定 -OpenCode 設定ファイルを通じて TUI の動作をカスタマイズできます。 +`tui.json` (または `tui.jsonc`) ファイルを通じて TUI の動作をカスタマイズできます。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +これは、サーバー/ランタイムの動作を構成する `opencode.json` とは別です。 + ### オプション -- `scroll_acceleration` - macOS スタイルのスクロールアクセラレーションを有効にして、スムーズで自然なスクロールを実現します。有効にすると、高速スクロールジェスチャではスクロール速度が向上し、ゆっくりとした動きでは正確なままになります。 **この設定は `scroll_speed` よりも優先され、有効になっている場合は上書きされます。** -- `scroll_speed` - スクロールコマンドを使用するときに TUI がスクロールする速度を制御します (最小: `1`)。デフォルトは `3` です。 **注: `scroll_acceleration.enabled` が `true` に設定されている場合、これは無視されます。** +- `theme` - UI テーマを設定します。[詳細はこちら](/docs/themes)。 +- `keybinds` - キーボードショートカットをカスタマイズします。[詳細はこちら](/docs/keybinds)。 +- `scroll_acceleration.enabled` - macOS スタイルのスクロールアクセラレーションを有効にして、スムーズで自然なスクロールを実現します。有効にすると、高速スクロールジェスチャではスクロール速度が向上し、ゆっくりとした動きでは正確なままになります。 **この設定は `scroll_speed` よりも優先され、有効になっている場合は上書きされます。** +- `scroll_speed` - スクロールコマンドを使用するときに TUI がスクロールする速度を制御します (最小: `0.001`、小数をサポート)。デフォルトは `3` です。 **注: `scroll_acceleration.enabled` が `true` に設定されている場合、これは無視されます。** +- `diff_style` - 差分レンダリングを制御します。 `"auto"` はターミナルの幅に適応し、`"stacked"` は常に 1 列のレイアウトを表示します。 + +カスタム TUI 設定パスをロードするには、`OPENCODE_TUI_CONFIG` を使用します。 --- diff --git a/packages/web/src/content/docs/ja/zen.mdx b/packages/web/src/content/docs/ja/zen.mdx index 751ca45e45..c7121fb3b7 100644 --- a/packages/web/src/content/docs/ja/zen.mdx +++ b/packages/web/src/content/docs/ja/zen.mdx @@ -18,23 +18,19 @@ Zen は OpenCode の他のプロバイダーと同様に機能します。 OpenC ## 背景 -モデルはたくさんありますが、そのうちのほんの一部です -これらのモデルはコーディングエージェントとしてうまく機能します。さらに、ほとんどのプロバイダーは、 -構成が大きく異なります。したがって、まったく異なるパフォーマンスと品質が得られます。 +世の中には多数のモデルがありますが、コーディングエージェントとしてうまく機能するのはごく一部です。さらに、ほとんどのプロバイダーは構成が大きく異なるため、パフォーマンスと品質も大きく異なります。 :::tip -私たちは、OpenCode で適切に動作するモデルとプロバイダーの選択されたグループをテストしました。 +OpenCode で適切に動作する、厳選されたモデルとプロバイダーのグループをテストしました。 ::: -OpenRouter などを通じてモデルを使用している場合は、決してそうすることはできません。 -必要なモデルの最高のバージョンを入手しているかどうかを確認してください。 + +OpenRouter などを通じてモデルを使用している場合、必要なモデルの最高のバージョンを取得できているか確信が持てません。 これを修正するために、いくつかのことを行いました。 -1. 私たちは選択したモデルのグループをテストし、その方法についてチームと話し合いました。 - それらを実行するのが最善です。 +1. 選抜したモデルグループをテストし、それらを最適に実行する方法についてチームと話し合いました。 2. その後、いくつかのプロバイダーと協力して、これらが確実に提供されるようにしました。 -3. 最後に、モデルとプロバイダーの組み合わせをベンチマークし、次の結果を導き出しました。 - 私たちが自信を持ってお勧めするリストをご紹介します。 +3. 最後に、モデルとプロバイダーの組み合わせをベンチマークし、自信を持ってお勧めできるリストを作成しました。 OpenCode Zen は、これらのモデルへのアクセスを可能にする AI ゲートウェイです。 @@ -44,8 +40,7 @@ OpenCode Zen は、これらのモデルへのアクセスを可能にする AI OpenCode Zen は、OpenCode の他のプロバイダーと同様に機能します。 -1. **OpenCode Zen** にログインし、請求内容を追加します - 詳細を確認し、API キーをコピーします。 +1. **OpenCode Zen** にサインインし、請求情報を追加して、API キーをコピーします。 2. TUI で `/connect` コマンドを実行し、OpenCode Zen を選択して API キーを貼り付けます。 3. TUI で `/models` を実行すると、推奨されるモデルのリストが表示されます。 @@ -59,6 +54,7 @@ OpenCode Zen は、OpenCode の他のプロバイダーと同様に機能しま | Model | Model ID | Endpoint | AI SDK Package | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -68,22 +64,24 @@ OpenCode Zen は、OpenCode の他のプロバイダーと同様に機能しま | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -112,29 +110,34 @@ https://opencode.ai/zen/v1/models | Model | Input | Output | Cached Read | Cached Write | | --------------------------------- | ------ | ------ | ----------- | ------------ | | Big Pickle | Free | Free | Free | - | -| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.5 Free | Free | Free | Free | - | +| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | - | | MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | -| GLM 4.7 Free | Free | Free | Free | - | +| GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 Free | Free | Free | Free | - | | Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - | +| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Claude Sonnet 4.6 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.6 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4.5 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | -| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - | @@ -151,10 +154,10 @@ https://opencode.ai/zen/v1/models クレジットカード手数料は実費で引き継がれます (4.4% + 取引ごとに 0.30 ドル)。それ以上の料金はかかりません。 ::: -- GLM 4.7 Free は期間限定で OpenCode で入手できます。チームはこの時間を利用してフィードバックを収集し、モデルを改善します。 -- Kim K2.5 Free は OpenCode で期間限定で利用可能です。チームはこの時間を利用してフィードバックを収集し、モデルを改善します。 -- MiniMax M2.1 Free は期間限定で OpenCode で入手できます。チームはこの時間を利用してフィードバックを収集し、モデルを改善します。 -- Big Pickle は、期間限定で OpenCode で無料で利用できるステルスモデルです。チームはこの時間を利用してフィードバックを収集し、モデルを改善します。 +無料のモデル: + +- MiniMax M2.5 Free は期間限定で OpenCode で利用可能です。チームはこの期間を利用してフィードバックを収集し、モデルを改善します。 +- Big Pickle は、期間限定で OpenCode で無料で利用できるステルスモデルです。チームはこの期間を利用してフィードバックを収集し、モデルを改善します。 ご質問がございましたら、お問い合わせください。 @@ -170,12 +173,9 @@ https://opencode.ai/zen/v1/models ### 月ごとの制限 -ワークスペース全体およびワークスペースごとに月ごとの使用制限を設定することもできます。 -あなたのチームのメンバー。 +ワークスペース全体およびチームの各メンバーの月ごとの使用制限を設定することもできます。 -たとえば、毎月の使用制限を 20 ドルに設定したとします。Zen は使用しません。 -月に20ドル以上。ただし、自動リロードを有効にしている場合、Zen が終了する可能性があります。 -残高が 5 ドルを下回ると、20 ドル以上の請求が行われます。 +たとえば、毎月の使用制限を 20 ドルに設定したとします。Zen は月に 20 ドル以上を使用しません。ただし、自動リロードを有効にしている場合、残高が 5 ドルを下回ると、Zen が 20 ドル以上の請求を行う可能性があります。 --- @@ -183,24 +183,22 @@ https://opencode.ai/zen/v1/models すべてのモデルは米国でホストされています。当社のプロバイダーはゼロ保持ポリシーに従い、次の例外を除いて、モデルのトレーニングにデータを使用しません。 -- Big Pickle: 無料期間中に、収集されたデータはモデルの改善に使用される場合があります。 -- GLM 4.7 無料: 無料期間中、収集されたデータはモデルを改善するために使用される場合があります。 -- Kimi K2.5 Free: 無料期間中、収集されたデータはモデルの改善に使用される場合があります。 -- MiniMax M2.1 無料: 無料期間中、収集されたデータはモデルを改善するために使用される場合があります。 -- OpenAI API: リクエストは [OpenAI のデータポリシー](https://platform.openai.com/docs/guides/your-data)に従います。 -- Anthropic API: リクエストは、[Anthropic のデータポリシー](https://docs.anthropic.com/en/docs/claude-code/data-usage)に従います。 +- Big Pickle: 無料期間中、収集されたデータはモデルの改善に使用される場合があります。 +- MiniMax M2.5 Free: 無料期間中、収集されたデータはモデルの改善に使用される場合があります。 +- OpenAI API: リクエストは [OpenAI のデータポリシー](https://platform.openai.com/docs/guides/your-data) に従い、30 日間保持されます。 +- Anthropic API: リクエストは [Anthropic のデータポリシー](https://docs.anthropic.com/en/docs/claude-code/data-usage) に従い、30 日間保持されます。 --- ## チーム向け -Zen はチームにも効果的です。チームメイトを招待し、役割を割り当て、キュレートすることができます -チームが使用するモデルなど。 +Zen はチームにも効果的です。チームメイトを招待し、役割を割り当て、チームが使用するモデルをキュレートすることなどができます。 :::note ワークスペースは現在、ベータ版の一部としてチームに無料で提供されています。 ::: -価格の詳細については近日中にお知らせします。 + +ワークスペースの管理は現在、ベータ版の一部としてチームに無料で提供されています。価格の詳細については近日中にお知らせします。 --- diff --git a/packages/web/src/content/docs/ko/config.mdx b/packages/web/src/content/docs/ko/config.mdx index e906eaf47b..2f08824d69 100644 --- a/packages/web/src/content/docs/ko/config.mdx +++ b/packages/web/src/content/docs/ko/config.mdx @@ -14,10 +14,11 @@ OpenCode는 **JSON**과 **JSONC**(주석이 포함된 JSON) 형식을 모두 지 ```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", - // Theme configuration - "theme": "opencode", "model": "anthropic/claude-sonnet-4-5", "autoupdate": true, + "server": { + "port": 4096, + }, } ``` @@ -33,7 +34,7 @@ config 파일은 **교체되지 않고 병합**됩니다. config 파일은 서로 대체되는 방식이 아니라 병합됩니다. 아래 config 위치의 설정이 결합되며, 충돌하는 key에 대해서만 나중에 로드된 config가 앞선 값을 override합니다. 충돌하지 않는 설정은 모두 유지됩니다. -예를 들어, 전역 config에 `theme: "opencode"`와 `autoupdate: true`가 있고 프로젝트 config에 `model: "anthropic/claude-sonnet-4-5"`가 있으면 최종 config에는 이 세 설정이 모두 포함됩니다. +예를 들어, 전역 config에 `autoupdate: true`가 있고 프로젝트 config에 `model: "anthropic/claude-sonnet-4-5"`가 있으면 최종 config에는 이 설정이 모두 포함됩니다. --- @@ -94,7 +95,9 @@ Remote config는 가장 먼저 로드되어 기본 레이어 역할을 합니다 ### Global -전역 OpenCode config는 `~/.config/opencode/opencode.json`에 두세요. theme, provider, keybind 같은 사용자 전체 기본 설정은 전역 config로 관리하세요. +전역 OpenCode config는 `~/.config/opencode/opencode.json`에 두세요. provider, model, permissions 같은 사용자 전체 기본 설정은 전역 config로 관리하세요. + +TUI 관련 설정은 `~/.config/opencode/tui.json`을 사용하세요. 전역 config는 조직의 Remote 기본값을 override합니다. @@ -104,6 +107,8 @@ Remote config는 가장 먼저 로드되어 기본 레이어 역할을 합니다 프로젝트 루트에 `opencode.json`을 추가하세요. 프로젝트 config는 표준 config 파일 중 우선순위가 가장 높아 전역 및 Remote config를 모두 override합니다. +프로젝트별 TUI 설정은 `tui.json`을 함께 추가하세요. + :::tip 프로젝트별 config는 프로젝트 루트에 두세요. ::: @@ -142,7 +147,9 @@ custom 디렉토리는 전역 config와 `.opencode` 디렉토리 뒤에 로드 ## Schema -config 파일의 schema는 [**`opencode.ai/config.json`**](https://opencode.ai/config.json)에 정의되어 있습니다. +server/runtime config schema는 [**`opencode.ai/config.json`**](https://opencode.ai/config.json)에 정의되어 있습니다. + +TUI config는 [**`opencode.ai/tui.json`**](https://opencode.ai/tui.json)을 사용합니다. 편집기에서 이 schema를 기반으로 validation과 autocomplete를 사용할 수 있습니다. @@ -150,28 +157,24 @@ config 파일의 schema는 [**`opencode.ai/config.json`**](https://opencode.ai/c ### TUI -`tui` 옵션으로 TUI 관련 설정을 구성할 수 있습니다. +TUI 관련 설정에는 전용 `tui.json` (또는 `tui.jsonc`) 파일을 사용하세요. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - }, - "diff_style": "auto" - } + "$schema": "https://opencode.ai/tui.json", + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` -사용 가능한 옵션: +`OPENCODE_TUI_CONFIG`를 사용하여 사용자 지정 TUI 설정 파일을 가리킬 수 있습니다. -- `scroll_acceleration.enabled` - macOS 스타일 스크롤 가속을 활성화합니다. **`scroll_speed`보다 우선합니다.** -- `scroll_speed` - 사용자 정의 스크롤 속도 배수(기본: `3`, 최소: `1`). `scroll_acceleration.enabled`가 `true`이면 무시됩니다. -- `diff_style` - diff 렌더링 방식을 제어합니다. `"auto"`는 터미널 너비에 맞춰 조정되고, `"stacked"`는 항상 단일 컬럼으로 표시합니다. +`opencode.json`의 기존 `theme`, `keybinds`, `tui` 키는 더 이상 사용되지 않으며(deprecated) 가능한 경우 자동으로 마이그레이션됩니다. -[TUI에 대해 더 알아보기](/docs/tui). +[TUI 구성에 대해 더 알아보기](/docs/tui#configure). --- @@ -297,12 +300,12 @@ Bearer token(`AWS_BEARER_TOKEN_BEDROCK` 또는 `/connect`)은 profile 기반 인 ### Themes -`theme` 옵션으로 OpenCode config에서 사용할 theme를 설정할 수 있습니다. +`tui.json`에서 UI 테마를 설정하세요. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "theme": "" + "$schema": "https://opencode.ai/tui.json", + "theme": "tokyonight" } ``` @@ -402,11 +405,11 @@ Bearer token(`AWS_BEARER_TOKEN_BEDROCK` 또는 `/connect`)은 profile 기반 인 ### Keybinds -`keybinds` 옵션으로 keybind를 커스터마이즈할 수 있습니다. +`tui.json`에서 단축키를 사용자 지정하세요. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": {} } ``` diff --git a/packages/web/src/content/docs/ko/custom-tools.mdx b/packages/web/src/content/docs/ko/custom-tools.mdx index 77310557fa..c90db16f1d 100644 --- a/packages/web/src/content/docs/ko/custom-tools.mdx +++ b/packages/web/src/content/docs/ko/custom-tools.mdx @@ -79,6 +79,32 @@ export const multiply = tool({ --- +#### 기본 도구와 이름 충돌 + +커스텀 도구는 도구 이름으로 식별됩니다. 커스텀 도구가 기본 도구와 같은 이름을 사용하면 커스텀 도구가 우선순위를 갖습니다. + +예를 들어, 이 파일은 기본 `bash` 도구를 대체합니다: + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +의도적으로 기본 도구를 대체하려는 경우가 아니라면 고유한 이름을 사용하는 것이 좋습니다. 도구를 오버라이드하지 않고 비활성화만 하려면 [permissions](/docs/permissions)를 사용하세요. +::: + +--- + ### 인자 인자 타입은 `tool.schema`로 정의할 수 있습니다. `tool.schema`는 [Zod](https://zod.dev) 기반입니다. diff --git a/packages/web/src/content/docs/ko/go.mdx b/packages/web/src/content/docs/ko/go.mdx new file mode 100644 index 0000000000..5909a01c9f --- /dev/null +++ b/packages/web/src/content/docs/ko/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: 오픈 코딩 모델을 위한 저렴한 구독 서비스입니다. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go는 인기 있는 오픈 코딩 모델에 안정적으로 액세스할 수 있는 저렴한 **월 $10** 구독 서비스입니다. + +:::note +OpenCode Go는 현재 베타 버전입니다. +::: + +Go는 OpenCode의 다른 제공자처럼 작동합니다. OpenCode Go를 구독하고 API 키를 받으세요. 이는 **완전히 선택 사항**이며 OpenCode를 사용하기 위해 반드시 사용할 필요는 없습니다. + +주로 해외 사용자를 위해 설계되었으며, 안정적인 글로벌 액세스를 위해 미국, EU, 싱가포르에서 모델이 호스팅됩니다. + +--- + +## 배경 + +오픈 모델은 정말 좋아졌습니다. 이제 코딩 작업에서 독점 모델에 가까운 성능을 발휘합니다. 그리고 많은 제공자가 경쟁적으로 서비스할 수 있기 때문에 일반적으로 훨씬 저렴합니다. + +하지만 안정적이고 지연 시간이 짧은 액세스를 얻기는 어려울 수 있습니다. 제공자마다 품질과 가용성이 다릅니다. + +:::tip +OpenCode와 잘 작동하는 엄선된 모델 및 제공자 그룹을 테스트했습니다. +::: + +이를 해결하기 위해 몇 가지 작업을 수행했습니다. + +1. 엄선된 오픈 모델 그룹을 테스트하고 해당 팀과 최적의 실행 방법에 대해 논의했습니다. +2. 그런 다음 몇몇 제공자와 협력하여 이것들이 올바르게 서비스되고 있는지 확인했습니다. +3. 마지막으로 모델/제공자 조합을 벤치마킹하여 추천할 만한 목록을 만들었습니다. + +OpenCode Go를 사용하면 **월 $10**에 이러한 모델에 액세스할 수 있습니다. + +--- + +## 작동 방식 + +OpenCode Go는 OpenCode의 다른 제공자처럼 작동합니다. + +1. **OpenCode Zen**에 로그인하고 Go를 구독한 다음 API 키를 복사합니다. +2. TUI에서 `/connect` 명령을 실행하고 `OpenCode Go`를 선택한 다음 API 키를 붙여넣습니다. +3. TUI에서 `/models`를 실행하여 Go를 통해 사용할 수 있는 모델 목록을 확인합니다. + +:::note +워크스페이스당 한 명의 멤버만 OpenCode Go를 구독할 수 있습니다. +::: + +현재 모델 목록은 다음과 같습니다. + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +모델 목록은 테스트하고 새로운 모델을 추가함에 따라 변경될 수 있습니다. + +--- + +## 사용 한도 + +OpenCode Go에는 다음과 같은 한도가 포함됩니다. + +- **5시간 한도** — $12 사용량 +- **주간 한도** — $30 사용량 +- **월간 한도** — $60 사용량 + +한도는 달러 가치로 정의됩니다. 즉, 실제 요청 수는 사용하는 모델에 따라 다릅니다. MiniMax M2.5와 같은 저렴한 모델은 더 많은 요청을 허용하는 반면, GLM-5와 같은 고비용 모델은 더 적은 요청을 허용합니다. + +아래 표는 일반적인 Go 사용 패턴을 기반으로 한 예상 요청 수를 제공합니다. + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| --------------- | ----- | --------- | ------------ | +| 5시간당 요청 수 | 1,150 | 1,850 | 30,000 | +| 주당 요청 수 | 2,880 | 4,630 | 75,000 | +| 월당 요청 수 | 5,750 | 9,250 | 150,000 | + +추정치는 관찰된 평균 요청 패턴을 기반으로 합니다. + +- GLM-5 — 요청당 입력 700, 캐시 52,000, 출력 150 토큰 +- Kimi K2.5 — 요청당 입력 870, 캐시 55,000, 출력 200 토큰 +- MiniMax M2.5 — 요청당 입력 300, 캐시 55,000, 출력 125 토큰 + +**콘솔**에서 현재 사용량을 추적할 수 있습니다. + +:::tip +사용 한도에 도달하면 무료 모델을 계속 사용할 수 있습니다. +::: + +사용 한도는 초기 사용 및 피드백을 통해 학습함에 따라 변경될 수 있습니다. + +--- + +### 가격 + +OpenCode Go는 **월 $10** 구독 요금제입니다. 아래는 **100만 토큰당** 가격입니다. + +| Model | Input | Output | Cached Read | +| ------------ | ----- | ------ | ----------- | +| GLM-5 | $1.00 | $3.20 | $0.20 | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | +| MiniMax M2.5 | $0.30 | $1.20 | $0.03 | + +--- + +### 한도 초과 사용 + +Zen 잔액에 크레딧이 있는 경우 콘솔에서 **잔액 사용(Use balance)** 옵션을 활성화할 수 있습니다. 활성화하면 사용 한도에 도달했을 때 요청을 차단하는 대신 Zen 잔액을 사용하게 됩니다. + +--- + +## 엔드포인트 + +다음 API 엔드포인트를 통해 Go 모델에 액세스할 수도 있습니다. + +| Model | Model ID | Endpoint | AI SDK Package | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +OpenCode 설정의 [모델 ID](/docs/config/#models)는 `opencode-go/` 형식을 사용합니다. 예를 들어 Kimi K2.5의 경우 설정에서 `opencode-go/kimi-k2.5`를 사용합니다. + +--- + +## 개인정보 보호 + +이 플랜은 주로 해외 사용자를 위해 설계되었으며, 안정적인 글로벌 액세스를 위해 미국, EU, 싱가포르에서 모델이 호스팅됩니다. + +질문이 있으시면 문의해 주세요. + +--- + +## 목표 + +우리는 다음을 위해 OpenCode Go를 만들었습니다. + +1. 저렴한 구독으로 더 많은 사람들이 AI 코딩에 **접근할 수 있도록** 합니다. +2. 최고의 오픈 코딩 모델에 **안정적으로** 액세스할 수 있도록 합니다. +3. 코딩 에이전트 사용을 위해 **테스트 및 벤치마킹된** 모델을 큐레이팅합니다. +4. OpenCode와 함께 다른 제공자도 사용할 수 있도록 하여 **락인(lock-in)이 없도록** 합니다. diff --git a/packages/web/src/content/docs/ko/keybinds.mdx b/packages/web/src/content/docs/ko/keybinds.mdx index aef7ae357a..2920a22357 100644 --- a/packages/web/src/content/docs/ko/keybinds.mdx +++ b/packages/web/src/content/docs/ko/keybinds.mdx @@ -3,11 +3,11 @@ title: 키바인드 description: 키바인드를 커스터마이즈하세요. --- -OpenCode에는 OpenCode config를 통해 커스터마이즈할 수 있는 keybinds 목록이 있습니다. +OpenCode에는 `tui.json`을 통해 커스터마이즈할 수 있는 키바인드 목록이 있습니다. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -117,11 +117,11 @@ keybinds에 리더 키를 꼭 사용할 필요는 없지만, 사용하는 것을 ## 키바인드 비활성화 -config에 해당 키를 값 `"none"`으로 추가하면 keybind를 비활성화할 수 있습니다. +`tui.json`에 해당 키를 값 `"none"`으로 추가하면 키바인드를 비활성화할 수 있습니다. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/ko/plugins.mdx b/packages/web/src/content/docs/ko/plugins.mdx index 7214f32658..f20eb90c46 100644 --- a/packages/web/src/content/docs/ko/plugins.mdx +++ b/packages/web/src/content/docs/ko/plugins.mdx @@ -3,7 +3,7 @@ title: 플러그인 description: OpenCode를 확장하기 위해 자신만의 플러그인을 작성하세요. --- -플러그인은 다양한 이벤트와 사용자 정의 행동으로 후킹하여 opencode를 확장 할 수 있습니다. 플러그인을 만들 수 있습니다 새로운 기능을 추가, 외부 서비스와 통합, 또는 opencode의 기본 동작을 수정. +플러그인은 다양한 이벤트와 사용자 정의 행동으로 후킹하여 opencode를 확장 할 수 있습니다. 플러그인을 사용하여 새로운 기능을 추가하거나, 외부 서비스와 통합하거나, opencode의 기본 동작을 수정할 수 있습니다. 예를 들어, 커뮤니티에 의해 생성 된 [plugins](/docs/ecosystem#plugins)를 확인하십시오. @@ -11,18 +11,18 @@ description: OpenCode를 확장하기 위해 자신만의 플러그인을 작성 ## 플러그인 사용 -플러그인을로드하는 두 가지 방법이 있습니다. +플러그인을 로드하는 두 가지 방법이 있습니다. --- -## 로컬 파일에서 +### 로컬 파일에서 플러그인 디렉토리에 JavaScript 또는 TypeScript 파일을 배치합니다. - `.opencode/plugins/` - 프로젝트 레벨 플러그인 - `~/.config/opencode/plugins/` - 글로벌 플러그인 -이 디렉토리의 파일은 자동으로 시작에로드됩니다. +이 디렉토리의 파일은 시작 시 자동으로 로드됩니다. --- @@ -37,43 +37,42 @@ config 파일에 npm 패키지를 지정합니다. } ``` -일반 및 범위의 npm 패키지 모두 지원됩니다. +일반 패키지 및 스코프 npm 패키지 모두 지원됩니다. [ecosystem](/docs/ecosystem#plugins)에서 사용할 수 있는 플러그인을 찾아보세요. --- -## 플러그인이 설치되는 방법 +### 플러그인이 설치되는 방법 -**npm 플러그인**은 시작시 Bun을 사용하여 자동으로 설치됩니다. 패키지와 그들의 의존성은 `~/.cache/opencode/node_modules/`에서 캐시됩니다. +**npm 플러그인**은 시작시 Bun을 사용하여 자동으로 설치됩니다. 패키지와 그 의존성은 `~/.cache/opencode/node_modules/`에 캐시됩니다. -**로컬 플러그인**은 플러그인 디렉토리에서 직접로드됩니다. 외부 패키지를 사용하려면 구성 디렉토리 내 `package.json`를 작성해야 합니다 ([Dependencies](#dependencies)), 또는 플러그인을 npm에 게시하고 [config에 추가](/docs/config#plugins). +**로컬 플러그인**은 플러그인 디렉토리에서 직접 로드됩니다. 외부 패키지를 사용하려면 구성 디렉토리 내에 `package.json`을 작성해야 하거나([의존성](#의존성) 참조), 플러그인을 npm에 게시하고 [config에 추가](/docs/config#plugins)해야 합니다. --- -## 로드 순서 +### 로드 순서 -플러그인은 모든 소스에서로드되며 모든 후크는 순서대로 실행됩니다. 로드 순서는 다음과 같습니다: +플러그인은 모든 소스에서 로드되며 모든 후크는 순서대로 실행됩니다. 로드 순서는 다음과 같습니다: 1. 글로벌 구성 (`~/.config/opencode/opencode.json`) 2. 프로젝트 구성 (`opencode.json`) 3. 글로벌 플러그인 디렉토리 (`~/.config/opencode/plugins/`) 4. 프로젝트 플러그인 디렉토리 (`.opencode/plugins/`) -중복 npm 패키지는 한 번만 로드됩니다. 하지만, 로컬 플러그인과 같은 이름과 npm 플러그인은 모두 별도로로드됩니다. +중복된 이름과 버전의 npm 패키지는 한 번만 로드됩니다. 하지만 로컬 플러그인과 npm 플러그인의 이름이 비슷하더라도 둘 다 별도로 로드됩니다. --- ## 플러그인 만들기 -플러그인은 **JavaScript/TypeScript 모듈**입니다. -기능. 각 함수는 context 객체를 수신하고 Hooks 객체를 반환합니다. +플러그인은 하나 이상의 플러그인 함수를 내보내는 **JavaScript/TypeScript 모듈**입니다. 각 함수는 context 객체를 수신하고 hooks 객체를 반환합니다. --- ### 의존성 -로컬 플러그인 및 사용자 정의 도구는 외부 npm 패키지를 사용할 수 있습니다. `package.json`를 config 디렉토리에 추가하면 필요한 의존도가 있습니다. +로컬 플러그인 및 사용자 정의 도구는 외부 npm 패키지를 사용할 수 있습니다. config 디렉토리에 `package.json`을 추가하고 필요한 의존성을 명시하십시오. ```json title=".opencode/package.json" { @@ -83,7 +82,7 @@ config 파일에 npm 패키지를 지정합니다. } ``` -opencode는 `bun install`를 시작합니다. 플러그인 및 도구가 가져올 수 있습니다. +opencode는 시작 시 `bun install`을 실행하여 이를 설치합니다. 이후 플러그인 및 도구에서 가져올 수 있습니다. ```ts title=".opencode/plugins/my-plugin.ts" import { escape } from "shescape" @@ -113,19 +112,19 @@ export const MyPlugin = async ({ project, client, $, directory, worktree }) => { } ``` -플러그인 기능 수신: +플러그인 함수가 받는 인자: - `project`: 현재 프로젝트 정보. - `directory`: 현재 작업 디렉토리. - `worktree`: git worktree 경로. - `client`: AI와 상호 작용을 위한 opencode SDK 클라이언트. -- `$`: Bun's [shell API](https://bun.com/docs/runtime/shell) 명령어를 실행합니다. +- `$`: 명령어를 실행하기 위한 Bun의 [shell API](https://bun.com/docs/runtime/shell). --- ### TypeScript 지원 -TypeScript 플러그인의 경우 플러그인 패키지에서 유형을 가져올 수 있습니다. +TypeScript 플러그인의 경우 플러그인 패키지에서 타입을 가져올 수 있습니다. ```ts title="my-plugin.ts" {1} import type { Plugin } from "@opencode-ai/plugin" @@ -139,29 +138,29 @@ export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree --- -## 이벤트 +### 이벤트 -플러그인은 예제 섹션에서 아래에서 볼 때 이벤트에 가입 할 수 있습니다. 여기에 다른 이벤트의 목록입니다. +플러그인은 아래 예제 섹션에서 볼 수 있듯이 이벤트를 구독할 수 있습니다. 사용 가능한 이벤트 목록은 다음과 같습니다. -### 명령어 이벤트 +#### 명령어 이벤트 - `command.executed` -### 파일 이벤트 +#### 파일 이벤트 - `file.edited` - `file.watcher.updated` -### 설치 이벤트 +#### 설치 이벤트 - `installation.updated` -### LSP 이벤트 +#### LSP 이벤트 - `lsp.client.diagnostics` - `lsp.updated` -### 메시지 이벤트 +#### 메시지 이벤트 - `message.part.removed` - `message.part.updated` @@ -173,11 +172,11 @@ export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree - `permission.asked` - `permission.replied` -### 서버 이벤트 +#### 서버 이벤트 - `server.connected` -### 세션 이벤트 +#### 세션 이벤트 - `session.created` - `session.compacted` @@ -188,7 +187,7 @@ export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree - `session.status` - `session.updated` -### Todo 이벤트 +#### Todo 이벤트 - `todo.updated` @@ -196,7 +195,7 @@ export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree - `shell.env` -##### 도구 이벤트 +#### 도구 이벤트 - `tool.execute.after` - `tool.execute.before` @@ -211,11 +210,11 @@ export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree ## 예제 -opencode를 확장하기 위해 사용할 수있는 플러그인의 몇 가지 예입니다. +opencode를 확장하기 위해 사용할 수 있는 플러그인 예제입니다. --- -## 알림 보내기 +### 알림 보내기 특정 이벤트가 발생할 때 알림을 전송: @@ -232,7 +231,7 @@ export const NotificationPlugin = async ({ project, client, $, directory, worktr } ``` -macOS에서 AppleScript를 실행하려면 `osascript`를 사용하고 있습니다. 여기에 우리는 그것을 사용하여 알림을 보낼 수 있습니다. +macOS에서 AppleScript를 실행하기 위해 `osascript`를 사용하고 있습니다. 여기서는 알림을 보내는 데 사용합니다. :::note opencode 데스크톱 앱을 사용하는 경우 응답이 준비되어 있거나 세션 오류가 있을 때 시스템 알림을 자동으로 보낼 수 있습니다. @@ -242,7 +241,7 @@ opencode 데스크톱 앱을 사용하는 경우 응답이 준비되어 있거 ### .env 보호 -읽기 `.env` 파일에서 opencode를 방지하십시오: +opencode가 `.env` 파일을 읽지 못하도록 방지: ```javascript title=".opencode/plugins/env-protection.js" export const EnvProtection = async ({ project, client, $, directory, worktree }) => { @@ -260,7 +259,7 @@ export const EnvProtection = async ({ project, client, $, directory, worktree }) ### Inject 환경 변수 -환경 변수를 모든 shell 실행 (AI 도구 및 사용자 terminal)로 주사하십시오. +모든 shell 실행(AI 도구 및 사용자 terminal)에 환경 변수 주입: ```javascript title=".opencode/plugins/inject-env.js" export const InjectEnvPlugin = async () => { @@ -277,7 +276,7 @@ export const InjectEnvPlugin = async () => { ### 사용자 정의 도구 -플러그인은 opencode에 사용자 정의 도구를 추가 할 수 있습니다 : +플러그인은 opencode에 사용자 정의 도구를 추가할 수 있습니다: ```ts title=".opencode/plugins/custom-tools.ts" import { type Plugin, tool } from "@opencode-ai/plugin" @@ -300,13 +299,17 @@ export const CustomToolsPlugin: Plugin = async (ctx) => { } ``` -`tool` helper는 opencode가 호출 할 수있는 사용자 정의 도구를 만듭니다. Zod schema 기능을 가지고 도구 정의를 반환: +`tool` helper는 opencode가 호출할 수 있는 사용자 정의 도구를 만듭니다. Zod 스키마 함수를 받고 다음을 포함하는 도구 정의를 반환합니다: -- `description`: 도구는 무엇을 +- `description`: 도구가 하는 일 - `args`: 도구의 인수에 대한 Zod 스키마 -- `execute`: 도구가 호출될 때 실행되는 기능 +- `execute`: 도구가 호출될 때 실행되는 함수 -사용자 정의 도구는 내장 도구와 함께 opencode를 사용할 수 있습니다. +사용자 정의 도구는 내장 도구와 함께 opencode에서 사용할 수 있습니다. + +:::note +플러그인 도구가 내장 도구와 같은 이름을 사용하면 플러그인 도구가 우선순위를 갖습니다. +::: --- @@ -331,9 +334,9 @@ export const MyPlugin = async ({ client }) => { --- -## Compaction 훅 +### Compaction 훅 -세션이 압축 될 때 포함 된 컨텍스트를 사용자 지정: +세션이 압축될 때 포함되는 컨텍스트를 사용자 지정할 수 있습니다: ```ts title=".opencode/plugins/compaction.ts" import type { Plugin } from "@opencode-ai/plugin" @@ -355,9 +358,9 @@ Include any state that should persist across compaction: } ``` -LLM이 압축 요약을 생성하기 전에 `experimental.session.compacting` 훅이 실행됩니다. 기본 압축 프롬프트를 대체할 수 있도록 도메인 별 컨텍스트를 주입합니다. +`experimental.session.compacting` 훅은 LLM이 연속 요약을 생성하기 전에 실행됩니다. 기본 압축 프롬프트가 놓칠 수 있는 도메인별 컨텍스트를 주입하는 데 사용하세요. -당신은 또한 `output.prompt`를 조정해서 조밀함을 전적으로 대체할 수 있습니다: +또한 `output.prompt`를 설정하여 압축 프롬프트를 완전히 대체할 수도 있습니다: ```ts title=".opencode/plugins/custom-compaction.ts" import type { Plugin } from "@opencode-ai/plugin" @@ -382,4 +385,4 @@ Format as a structured prompt that a new agent can use to resume work. } ``` -`output.prompt`가 설정되면 완전히 기본 압축 프롬프트를 대체합니다. `output.context` 배열은 이 경우에 무시됩니다. +`output.prompt`가 설정되면 기본 압축 프롬프트를 완전히 대체합니다. 이 경우 `output.context` 배열은 무시됩니다. diff --git a/packages/web/src/content/docs/ko/providers.mdx b/packages/web/src/content/docs/ko/providers.mdx index ea48dbfb0a..c543c719dd 100644 --- a/packages/web/src/content/docs/ko/providers.mdx +++ b/packages/web/src/content/docs/ko/providers.mdx @@ -22,13 +22,13 @@ OpenCode는 [AI SDK](https://ai-sdk.dev/) 및 [Models.dev](https://models.dev) --- -#### 구성 +### 구성 OpenCode 설정의 `provider` 섹션을 통해 공급자를 사용자 정의할 수 있습니다. --- -### 기본 URL +#### 기본 URL `baseURL` 옵션을 설정하여 모든 공급자를 위한 기본 URL을 사용자 정의할 수 있습니다. 프록시 서비스 또는 사용자 정의 엔드포인트를 사용할 때 유용합니다. @@ -55,7 +55,38 @@ OpenCode Zen은 OpenCode 팀이 OpenCode와 잘 작동하도록 테스트하고 처음이라면 OpenCode Zen으로 시작하는 것이 좋습니다. ::: -1. TUI에서 `/connect` 명령을 실행하고 `opencode`를 선택한 뒤, [opencode.ai/auth](https://opencode.ai/auth)로 이동합니다. +1. TUI에서 `/connect` 명령을 실행하고 `OpenCode Zen`을 선택한 뒤, [opencode.ai/auth](https://opencode.ai/zen)로 이동합니다. + + ```txt + /connect + ``` + +2. 로그인하고 결제 정보를 입력한 후 API 키를 복사하십시오. + +3. API 키를 붙여넣습니다. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. TUI에서 `/models`를 실행하여 추천 모델 목록을 볼 수 있습니다. + + ```txt + /models + ``` + +OpenCode의 다른 공급자처럼 작동하며 사용은 완전히 선택 사항입니다. + +--- + +## OpenCode Go + +OpenCode Go는 OpenCode 팀이 테스트하고 검증하여 OpenCode와 잘 작동하는 인기 있는 오픈 코딩 모델에 안정적으로 액세스할 수 있는 저렴한 구독 요금제입니다. + +1. TUI에서 `/connect` 명령을 실행하고 `OpenCode Go`를 선택한 뒤 [opencode.ai/auth](https://opencode.ai/zen)로 이동하십시오. ```txt /connect @@ -129,15 +160,15 @@ OpenCode로 Amazon Bedrock을 사용하려면: Amazon Bedrock에서 원하는 모델에 대한 액세스 권한이 있어야 합니다. ::: -2. 다음 방법 중 하나를 사용하여 **설정**합니다: +2. 다음 방법 중 하나를 사용하여 **인증을 구성**합니다: ---- + *** -### 환경 변수 (빠른 시작) + #### 환경 변수 (빠른 시작) -OpenCode를 실행하는 동안 다음 환경 변수 중 하나를 설정합니다: + OpenCode를 실행하는 동안 다음 환경 변수 중 하나를 설정합니다: -```bash + ```bash # Option 1: Using AWS access keys AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=YYY opencode @@ -146,87 +177,84 @@ OpenCode를 실행하는 동안 다음 환경 변수 중 하나를 설정합니 # Option 3: Using Bedrock bearer token AWS_BEARER_TOKEN_BEDROCK=XXX opencode -``` + ``` -또는 bash 프로필에 추가합니다: + 또는 bash 프로필에 추가합니다: -```bash title="~/.bash_profile" + ```bash title="~/.bash_profile" export AWS_PROFILE=my-dev-profile export AWS_REGION=us-east-1 -``` + ``` ---- + *** -#### 설정 파일 (권장) + #### 구성 파일 (권장) -프로젝트별 또는 영구 구성을 위해 `opencode.json`을 사용하십시오. + 프로젝트별 또는 영구 구성을 위해 `opencode.json`을 사용하십시오: -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "provider": { - "amazon-bedrock": { - "options": { - "region": "us-east-1", - "profile": "my-aws-profile" - } - } - } -} -``` + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "my-aws-profile" + } + } + } + } + ``` -**유효한 옵션:** + **유효한 옵션:** + - `region` - AWS 리전 (예: `us-east-1`, `eu-west-1`) + - `profile` - `~/.aws/credentials`의 AWS 프로필 이름 + - `endpoint` - VPC 엔드포인트 등을 위한 사용자 정의 엔드포인트 URL (일반 `baseURL` 옵션의 별칭) -- `region` - AWS 리전 (예: `us-east-1`, `eu-west-1`) -- `profile` - `~/.aws/credentials`의 AWS 프로필 이름 -- `endpoint` - VPC 엔드포인트 등을 위한 사용자 정의 엔드포인트 URL (일반 `baseURL` 옵션의 별칭) + :::tip + 구성 파일 옵션은 환경 변수보다 우선 순위가 높습니다. + ::: - :::tip - 구성 파일 옵션은 환경 변수보다 우선 순위가 높습니다. - ::: + *** ---- + #### 고급: VPC 엔드포인트 -#### 고급: VPC 엔드포인트 + Bedrock의 VPC 엔드포인트를 사용하는 경우: -Bedrock의 VPC 엔드포인트를 사용하는 경우: + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "amazon-bedrock": { + "options": { + "region": "us-east-1", + "profile": "production", + "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" + } + } + } + } + ``` -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "provider": { - "amazon-bedrock": { - "options": { - "region": "us-east-1", - "profile": "production", - "endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com" - } - } - } -} -``` + :::note + `endpoint` 옵션은 일반적인 `baseURL` 옵션의 별칭입니다. `endpoint`와 `baseURL` 둘 다 지정된 경우 `endpoint`가 우선합니다. + ::: -:::note -`endpoint` 옵션은 일반적인 `baseURL` 옵션의 별칭입니다. `endpoint`와 `baseURL` 둘 다 지정된 경우 `endpoint`가 우선합니다. -::: + *** ---- + #### 인증 방법 + - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: IAM 사용자 및 AWS 콘솔에서 액세스 키 생성 + - **`AWS_PROFILE`**: `~/.aws/credentials`의 프로필 이름을 사용합니다. `aws configure --profile my-profile` 또는 `aws sso login`으로 먼저 구성하십시오. + - **`AWS_BEARER_TOKEN_BEDROCK`**: Amazon Bedrock 콘솔에서 임시 API 키 생성 + - **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: EKS IRSA (서비스 계정용 IAM 역할) 또는 다른 Kubernetes 환경의 OIDC 연동. 이 환경 변수는 서비스 계정을 사용할 때 Kubernetes에 의해 자동으로 주입됩니다. -#### 인증 방법 + *** -- **`AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`**: IAM 사용자 및 AWS 콘솔에서 액세스 키 생성 -- **`AWS_PROFILE`**: `~/.aws/credentials`의 프로필 이름을 사용합니다. `aws configure --profile my-profile` 또는 `aws sso login`으로 먼저 구성하십시오. -- **`AWS_BEARER_TOKEN_BEDROCK`**: Amazon Bedrock 콘솔에서 임시 API 키 생성 -- **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: EKS IRSA (서비스 계정용 IAM 역할) 또는 다른 Kubernetes 환경의 OIDC 연동. 이 환경 변수는 서비스 계정을 사용할 때 Kubernetes에 의해 자동으로 주입됩니다. + #### 인증 우선 순위 ---- - -#### 인증 우선 순위 - -Amazon Bedrock은 다음과 같은 인증 우선 순위를 사용합니다. - -1. **Bearer Token** - `AWS_BEARER_TOKEN_BEDROCK` 환경 변수 또는 `/connect` 명령의 토큰 -2. **AWS Credential Chain** - 프로필, 액세스 키, 공유 자격 증명, IAM 역할, 웹 ID 토큰 (EKS IRSA), 인스턴스 메타데이터 + Amazon Bedrock은 다음과 같은 인증 우선 순위를 사용합니다. + 1. **Bearer Token** - `AWS_BEARER_TOKEN_BEDROCK` 환경 변수 또는 `/connect` 명령의 토큰 + 2. **AWS Credential Chain** - 프로필, 액세스 키, 공유 자격 증명, IAM 역할, 웹 ID 토큰 (EKS IRSA), 인스턴스 메타데이터 :::note Bearer 토큰을 설정할 때 (`/connect` 또는 `AWS_BEARER_TOKEN_BEDROCK`를 통해), 구성된 프로필을 포함한 모든 AWS 자격 증명 방법보다 우선 순위가 높습니다. @@ -260,7 +288,7 @@ Amazon Bedrock은 다음과 같은 인증 우선 순위를 사용합니다. --- -#### Anthropic +### Anthropic 1. 가입 후 `/connect` 명령을 실행하고 **Anthropic**을 선택합니다. @@ -268,7 +296,7 @@ Amazon Bedrock은 다음과 같은 인증 우선 순위를 사용합니다. /connect ``` -2. **Claude Pro/Max** 옵션을 선택하면 브라우저가 열립니다. +2. **Claude Pro/Max** 옵션을 선택하면 브라우저가 열리고 인증을 요청합니다. ```txt ┌ Select auth method @@ -300,7 +328,7 @@ Pro/Max 구독이 없는 경우 **Create an API Key**를 선택할 수 있습니 ### Azure OpenAI :::note -"I'm sorry, but I can't support that request" 오류가 발생하면, Azure 리소스의 콘텐츠 필터를 **DefaultV2**에서 **Default**로 변경해 보세요. +"I'm sorry, but I cannot assist with that request" 오류가 발생하면, Azure 리소스의 콘텐츠 필터를 **DefaultV2**에서 **Default**로 변경해 보세요. ::: 1. [Azure 포털](https://portal.azure.com/)로 이동하여 **Azure OpenAI** 리소스를 만듭니다. 다음이 필요합니다: @@ -395,7 +423,7 @@ Pro/Max 구독이 없는 경우 **Create an API Key**를 선택할 수 있습니 --- -#### Baseten +### Baseten 1. [Baseten](https://app.baseten.co/)으로 이동하여 계정을 만들고 API 키를 생성합니다. @@ -422,7 +450,7 @@ Pro/Max 구독이 없는 경우 **Create an API Key**를 선택할 수 있습니 --- -#### Cerebras +### Cerebras 1. [Cerebras 콘솔](https://inference.cerebras.ai/)로 이동하여 계정을 만들고 API 키를 생성합니다. @@ -441,7 +469,7 @@ Pro/Max 구독이 없는 경우 **Create an API Key**를 선택할 수 있습니 └ enter ``` -4. `/models` 명령을 실행하여 모델(예: Qwen 3 Coder 480B)을 선택하십시오. +4. `/models` 명령을 실행하여 모델(예: _Qwen 3 Coder 480B_)을 선택하십시오. ```txt /models @@ -449,7 +477,7 @@ Pro/Max 구독이 없는 경우 **Create an API Key**를 선택할 수 있습니 --- -## Cloudflare AI Gateway +### Cloudflare AI Gateway Cloudflare AI Gateway는 OpenAI, Anthropic, Workers AI 등의 모델에 액세스할 수 있으며, 통합된 엔드포인트를 통해 더 많은 기능을 제공합니다. [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/)을 사용하면 각 공급자의 별도 API 키가 필요하지 않습니다. @@ -507,7 +535,7 @@ Cloudflare AI Gateway는 OpenAI, Anthropic, Workers AI 등의 모델에 액세 --- -#### Cortecs +### Cortecs 1. [Cortecs 콘솔](https://cortecs.ai/)로 이동하여 계정을 만들고 API 키를 생성합니다. @@ -526,7 +554,7 @@ Cloudflare AI Gateway는 OpenAI, Anthropic, Workers AI 등의 모델에 액세 └ enter ``` -4. `/models` 명령을 실행하여 모델(예: Kimi K2 Instruct)을 선택하십시오. +4. `/models` 명령을 실행하여 모델(예: _Kimi K2 Instruct_)을 선택하십시오. ```txt /models @@ -534,7 +562,7 @@ Cloudflare AI Gateway는 OpenAI, Anthropic, Workers AI 등의 모델에 액세 --- -## DeepSeek +### DeepSeek 1. [DeepSeek 콘솔](https://platform.deepseek.com/)로 이동하여 계정을 만들고 **API Keys**를 클릭하여 키를 생성합니다. @@ -553,7 +581,7 @@ Cloudflare AI Gateway는 OpenAI, Anthropic, Workers AI 등의 모델에 액세 └ enter ``` -4. `/models` 명령을 실행하여 DeepSeek 모델(예: DeepSeek Reasoner)을 선택하십시오. +4. `/models` 명령을 실행하여 DeepSeek 모델(예: _DeepSeek Reasoner_)을 선택하십시오. ```txt /models @@ -561,7 +589,7 @@ Cloudflare AI Gateway는 OpenAI, Anthropic, Workers AI 등의 모델에 액세 --- -## Deep Infra +### Deep Infra 1. [Deep Infra 대시보드](https://deepinfra.com/dash)로 이동하여 계정을 만들고 API 키를 생성합니다. @@ -588,7 +616,7 @@ Cloudflare AI Gateway는 OpenAI, Anthropic, Workers AI 등의 모델에 액세 --- -## Firmware +### Firmware 1. [Firmware 대시보드](https://app.firmware.ai/signup)로 이동하여 계정을 만들고 API 키를 생성합니다. @@ -615,7 +643,7 @@ Cloudflare AI Gateway는 OpenAI, Anthropic, Workers AI 등의 모델에 액세 --- -## Fireworks AI +### Fireworks AI 1. [Fireworks AI 콘솔](https://app.fireworks.ai/)로 이동하여 계정을 만들고 **API Keys**를 클릭합니다. @@ -634,7 +662,7 @@ Cloudflare AI Gateway는 OpenAI, Anthropic, Workers AI 등의 모델에 액세 └ enter ``` -4. `/models` 명령을 실행하여 모델(예: Kimi K2 Instruct)을 선택하십시오. +4. `/models` 명령을 실행하여 모델(예: _Kimi K2 Instruct_)을 선택하십시오. ```txt /models @@ -662,38 +690,33 @@ GitLab Duo는 GitLab의 Anthropic 프록시를 통해 기본 도구 호출 기 └ ``` -#### OAuth 사용 (권장) + #### OAuth 사용 (권장) -**OAuth**를 선택하면 브라우저에서 권한 부여를 요청합니다. + **OAuth**를 선택하면 브라우저가 열리고 인증을 요청합니다. ---- + #### 개인 액세스 토큰 사용 + 1. [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens)로 이동 + 2. **Add new token** 클릭 + 3. 이름: `OpenCode`, 범위: `api` + 4. 토큰 복사 (`glpat-`로 시작) + 5. 터미널에 입력 -### 개인 액세스 토큰 사용 - -1. [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens)로 이동 -2. 새 토큰 추가 -3. 이름: `OpenCode`, 범위: `api` -4. 토큰 복사 (`glpat-`로 시작) -5. 터미널에 입력하십시오. - -6. 사용 가능한 모델을 보려면 `/models` 명령을 실행하십시오. +3. `/models` 명령을 실행하여 사용 가능한 모델을 확인하십시오. ```txt /models ``` -세 가지 Claude 기반 모델을 사용할 수 있습니다: - -- **duo-chat-haiku-4-5** (기본값) - 빠른 작업을 위한 빠른 응답 -- **duo-chat-sonnet-4-5** - 대부분의 워크플로우에 균형 잡힌 성능 -- **duo-chat-opus-4-5** - 복잡한 분석 가능 + 세 가지 Claude 기반 모델을 사용할 수 있습니다: + - **duo-chat-haiku-4-5** (기본값) - 빠른 작업을 위한 빠른 응답 + - **duo-chat-sonnet-4-5** - 대부분의 워크플로우에 균형 잡힌 성능 + - **duo-chat-opus-4-5** - 복잡한 분석에 적합 :::note -`GITLAB_TOKEN` 환경 변수를 지정할 수도 있습니다. -OpenCode는 인증 저장소에 토큰을 저장합니다. +`GITLAB_TOKEN` 환경 변수를 지정하여 토큰을 저장하지 않고 사용할 수도 있습니다. ::: -#### 셀프 호스팅 GitLab (Self-Hosted) +#### 셀프 호스팅 GitLab :::note[규정 준수 참고 사항] OpenCode는 세션 제목 생성과 같은 일부 AI 작업을 위해 작은 모델을 사용합니다. @@ -711,7 +734,7 @@ OpenCode를 자체 호스팅 GitLab 인스턴스만 사용하도록 제한하려 ::: -자체 호스팅 GitLab 인스턴스: +자체 호스팅 GitLab 인스턴스의 경우: ```bash export GITLAB_INSTANCE_URL=https://gitlab.company.com @@ -721,7 +744,7 @@ export GITLAB_TOKEN=glpat-... 인스턴스가 사용자 정의 AI Gateway를 실행하는 경우: ```bash -export GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com +GITLAB_AI_GATEWAY_URL=https://ai-gateway.company.com ``` 또는 bash 프로필에 추가: @@ -737,19 +760,18 @@ GitLab 관리자는 다음을 활성화해야 합니다: 1. [Duo Agent Platform](https://docs.gitlab.com/user/gitlab_duo/turn_on_off/) (사용자, 그룹 또는 인스턴스) 2. 기능 플래그 (Rails 콘솔을 통해): - -- `agent_platform_claude_code` -- `third_party_agents_enabled` - ::: + - `agent_platform_claude_code` + - `third_party_agents_enabled` + ::: #### 셀프 호스팅 인스턴스용 OAuth 자체 호스팅 인스턴스에 대해 OAuth를 작동시키려면 새로운 애플리케이션(Settings → Applications)을 만들어야 합니다. 콜백 URL `http://127.0.0.1:8080/callback` 및 다음 범위가 필요합니다: -- `api` (사용자 대신 API 액세스) -- `read_user` (개인 정보 읽기) -- `read_repository` (리포지토리 읽기 전용 액세스) +- api (사용자 대신 API 액세스) +- read_user (개인 정보 읽기) +- read_repository (리포지토리 읽기 전용 액세스) 그런 다음 애플리케이션 ID를 환경 변수로 노출하십시오: @@ -759,7 +781,7 @@ export GITLAB_OAUTH_CLIENT_ID=your_application_id_here [opencode-gitlab-auth](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth) 홈페이지에 추가 문서가 있습니다. -##### 구성 +#### 구성 `opencode.json`을 통해 사용자 정의: @@ -780,7 +802,7 @@ export GITLAB_OAUTH_CLIENT_ID=your_application_id_here } ``` -##### GitLab API 도구 (선택 사항이지만 강력 권장) +#### GitLab API 도구 (선택 사항이지만 강력 권장) GitLab 도구(병합 요청, 이슈, 파이프라인, CI/CD 등)에 액세스하려면: @@ -797,13 +819,10 @@ GitLab 도구(병합 요청, 이슈, 파이프라인, CI/CD 등)에 액세스하 ### GitHub Copilot -GitHub Copilot 구독을 사용하여 opencode: +OpenCode에서 GitHub Copilot 구독을 사용하려면: :::note -몇몇 모형은 [Pro+를 필요로 할지도 모릅니다 -구독](https://github.com/features/copilot/plans) 사용. - -일부 모델은 수동으로 활성화해야합니다 [GitHub Copilot 설정](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use). +일부 모델은 [Pro+ 구독](https://github.com/features/copilot/plans)이 필요할 수 있습니다. ::: 1. `/connect` 명령을 실행하고 GitHub Copilot을 검색하십시오. @@ -821,7 +840,8 @@ GitHub Copilot 구독을 사용하여 opencode: │ │ Enter code: 8F43-6FCF │ - └ Waiting for authorization... + │ Waiting for authorization... + └ ``` 3. 이제 원하는 모델을 선택하기 위해 `/models` 명령을 실행합니다. @@ -832,44 +852,42 @@ GitHub Copilot 구독을 사용하여 opencode: --- -### 구글 Vertex AI +### Google Vertex AI -opencode로 Google Vertex AI를 사용하려면: +OpenCode로 Google Vertex AI를 사용하려면: -1. Google Cloud Console에서 ** Model Garden**을 통해 헤드를 확인하고 확인하십시오. - 당신의 지역에서 유효한 모형. +1. Google Cloud Console의 **Model Garden**으로 이동하여 해당 리전에서 사용 가능한 모델을 확인하십시오. :::note - Vertex AI API를 사용하여 Google Cloud 프로젝트를 수행해야합니다. + Vertex AI API가 활성화된 Google Cloud 프로젝트가 있어야 합니다. ::: 2. 필요한 환경 변수를 설정: + - `GOOGLE_CLOUD_PROJECT`: 구글 클라우드 프로젝트 ID + - `VERTEX_LOCATION` (선택): Vertex AI 리전 (기본값: `global`) + - 인증 (하나 선택): + - `GOOGLE_APPLICATION_CREDENTIALS`: 서비스 계정 JSON 키 파일 경로 + - gcloud CLI 사용: `gcloud auth application-default login` -- `GOOGLE_CLOUD_PROJECT`: 당신의 구글 클라우드 프로젝트 ID -- `VERTEX_LOCATION` (선택): Vertex AI를 위한 지구 (`global`에 기본) -- 인증(초당): -- `GOOGLE_APPLICATION_CREDENTIALS`: 서비스 계정 JSON 키 파일 경로 -- gcloud CLI를 사용하여 인증 : `gcloud auth application-default login` + OpenCode를 실행할 때 설정: -opencode를 실행하면서 설정한다. - -```bash + ```bash GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode -``` + ``` -또는 bash 프로파일에 추가하십시오. + 또는 bash 프로필에 추가: -```bash title="~/.bash_profile" + ```bash title="~/.bash_profile" export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json export GOOGLE_CLOUD_PROJECT=your-project-id export VERTEX_LOCATION=global -``` + ``` :::tip -`global` 지구는 가용성을 개량하고 추가 비용 없이 과실을 감소시킵니다. 데이터 거주 요건에 대한 지역 엔드포인트(e.g., `us-central1`)를 사용하십시오. [더 알아보기](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional and global endpoints) +`global` 리전은 가용성을 높이고 오류를 줄이며 추가 비용이 없습니다. 데이터 거주 요건이 있는 경우 지역 엔드포인트(예: `us-central1`)를 사용하십시오. [더 알아보기](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-partner-models#regional_and_global_endpoints) ::: -3. 당신이 원하는 모형을 선정하기 위하여 `/models` 명령을 실행하십시오. +3. `/models` 명령을 실행하여 원하는 모델을 선택하십시오. ```txt /models @@ -877,17 +895,17 @@ opencode를 실행하면서 설정한다. --- -##### Groq +### Groq -1. [Groq 콘솔](https://console.groq.com/)에 머리, click **Create API Key**, 키 복사. +1. [Groq 콘솔](https://console.groq.com/)로 이동하여 **Create API Key**를 클릭하고 키를 복사합니다. -2. `/connect` 명령을 실행하고 Groq에 대한 검색. +2. `/connect` 명령을 실행하고 Groq를 검색하십시오. ```txt /connect ``` -3. 공급자를 위한 API 열쇠를 입력하십시오. +3. API 키를 입력하십시오. ```txt ┌ API key @@ -896,7 +914,7 @@ opencode를 실행하면서 설정한다. └ enter ``` -4. `/models` 명령을 실행하여 원하는 것을 선택합니다. +4. `/models` 명령을 실행하여 원하는 모델을 선택합니다. ```txt /models @@ -906,9 +924,9 @@ opencode를 실행하면서 설정한다. ### Hugging Face -[Hugging Face Inference Provider](https://huggingface.co/docs/inference-providers)는 17+ 공급자가 지원하는 오픈 모델에 대한 액세스를 제공합니다. +[Hugging Face Inference Providers](https://huggingface.co/docs/inference-providers)는 17개 이상의 공급자가 지원하는 오픈 모델에 대한 액세스를 제공합니다. -1. [Hugging Face settings](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained)를 통해 토큰을 Inference Provider에게 호출할 권한을 부여합니다. +1. [Hugging Face settings](https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained)로 이동하여 Inference Providers에 호출할 권한이 있는 토큰을 생성합니다. 2. `/connect` 명령을 실행하고 **Hugging Face**를 검색하십시오. @@ -925,7 +943,7 @@ opencode를 실행하면서 설정한다. └ enter ``` -4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 Kimi-K2-Instruct 또는 GLM-4.6 . +4. `/models` 명령을 실행하여 모델(예: _Kimi-K2-Instruct_ 또는 _GLM-4.6_)을 선택하십시오. ```txt /models @@ -935,17 +953,17 @@ opencode를 실행하면서 설정한다. ### Helicone -[Helicone](https://helicone.ai)는 AI 애플리케이션에 대한 로깅, 모니터링 및 분석 기능을 제공하는 LLM Observability 플랫폼입니다. Helicone AI Gateway는 모델을 기반으로 적절한 공급자에게 요청을 자동으로 전달합니다. +[Helicone](https://helicone.ai)는 AI 애플리케이션을 위한 로깅, 모니터링 및 분석 기능을 제공하는 LLM 관찰 가능성(Observability) 플랫폼입니다. Helicone AI Gateway는 모델을 기반으로 적절한 공급자에게 요청을 자동으로 라우팅합니다. -1. [Helicone](https://helicone.ai)에 머리, 계정을 만들고, 대시보드에서 API 키를 생성합니다. +1. [Helicone](https://helicone.ai)로 이동하여 계정을 만들고 대시보드에서 API 키를 생성합니다. -2. `/connect` 명령을 실행하고 ** Helicone**를 검색하십시오. +2. `/connect` 명령을 실행하고 **Helicone**를 검색하십시오. ```txt /connect ``` -3. Helicone API 열쇠를 입력하십시오. +3. Helicone API 키를 입력하십시오. ```txt ┌ API key @@ -954,19 +972,19 @@ opencode를 실행하면서 설정한다. └ enter ``` -4. 모델을 선택하려면 `/models` 명령을 실행하십시오. +4. `/models` 명령을 실행하여 모델을 선택하십시오. ```txt /models ``` -캐싱 및 속도 제한과 같은 더 많은 공급자와 고급 기능을 위해 [Helicone 문서](https://docs.helicone.ai)를 확인하십시오. +캐싱 및 속도 제한과 같은 더 많은 공급자와 고급 기능은 [Helicone 문서](https://docs.helicone.ai)를 확인하십시오. -#### 선택 사항 +#### 선택적 구성 -이벤트에서 opencode를 통해 자동으로 구성되지 않는 Helicone의 기능 또는 모델을 볼 수 있습니다. +OpenCode를 통해 자동으로 구성되지 않는 Helicone의 기능이나 모델이 있는 경우 직접 구성할 수 있습니다. -여기에 [Helicone의 모델 디렉토리](https://helicone.ai/models), 당신은 당신이 추가 할 모델의 ID를 잡아이 필요. +[Helicone의 모델 디렉토리](https://helicone.ai/models)에서 추가하려는 모델의 ID를 확인하십시오. ```jsonc title="~/.config/opencode/opencode.jsonc" { @@ -992,7 +1010,7 @@ opencode를 실행하면서 설정한다. } ``` -##### 사용자 정의 헤더 +#### 사용자 정의 헤더 Helicone는 캐싱, 사용자 추적 및 세션 관리와 같은 기능을 위한 사용자 정의 헤더를 지원합니다. `options.headers`를 사용하여 공급자 구성에 추가하십시오: @@ -1017,7 +1035,7 @@ Helicone는 캐싱, 사용자 추적 및 세션 관리와 같은 기능을 위 ##### 세션 추적 -Helicone's [Sessions](https://docs.helicone.ai/features/sessions) 기능으로 그룹 관련 LLM 요청이 가능합니다. [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) 플러그인을 사용하여 각 opencode 대화를 Helicone 세션으로 자동 로그인하십시오. +Helicone의 [Sessions](https://docs.helicone.ai/features/sessions) 기능을 사용하면 관련 LLM 요청을 그룹화할 수 있습니다. [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) 플러그인을 사용하여 각 OpenCode 대화를 Helicone 세션으로 자동 기록하십시오. ```bash npm install -g opencode-helicone-session @@ -1031,24 +1049,24 @@ npm install -g opencode-helicone-session } ``` -플러그인은 `Helicone-Session-Id` 및 `Helicone-Session-Name` 헤더를 귀하의 요청에 주사합니다. Helicone의 세션 페이지에서는 별도의 세션으로 나열된 각 opencode 대화를 볼 수 있습니다. +이 플러그인은 `Helicone-Session-Id` 및 `Helicone-Session-Name` 헤더를 요청에 주입합니다. Helicone의 세션 페이지에서 각 OpenCode 대화가 별도의 세션으로 나열되는 것을 볼 수 있습니다. -###### 공통 Helicone 헤더 +##### 공통 Helicone 헤더 -| 헤드러 | Description | +| 헤더 | 설명 | | -------------------------- | ---------------------------------------------------------- | -| `Helicone-Cache-Enabled` | 대응 캐싱 (`true`/`false`) | -| `Helicone-User-Id` | 사용자별 추적 가능 | +| `Helicone-Cache-Enabled` | 응답 캐싱 활성화 (`true`/`false`) | +| `Helicone-User-Id` | 사용자별 지표 추적 | | `Helicone-Property-[Name]` | 사용자 정의 속성 추가(예: `Helicone-Property-Environment`) | -| `Helicone-Prompt-Id` | prompt 대응 | +| `Helicone-Prompt-Id` | 요청을 프롬프트 버전과 연관 | -모든 사용 가능한 헤더에 대한 [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory)를 참조하십시오. +사용 가능한 모든 헤더는 [Helicone Header Directory](https://docs.helicone.ai/helicone-headers/header-directory)를 참조하십시오. --- -#### llama.cpp +### llama.cpp -[llama.cpp's](https://github.com/ggml-org/llama.cpp) llama-server 유틸리티를 통해 로컬 모델을 사용할 수 있습니다. +[llama.cpp](https://github.com/ggml-org/llama.cpp)의 llama-server 유틸리티를 통해 로컬 모델을 사용하도록 구성할 수 있습니다. ```json title="opencode.json" "llama.cpp" {5, 6, 8, 10-15} { @@ -1076,21 +1094,21 @@ npm install -g opencode-helicone-session 이 예제에서: -- `llama.cpp`는 주문 공급자 ID입니다. 원하는 문자열이 될 수 있습니다. -- `npm`는 이 공급자를 위해 사용할 포장을 지정합니다. 여기, `@ai-sdk/openai-compatible`는 OpenAI 호환 API에 사용됩니다. -- `name`는 UI에 있는 공급자를 위한 전시 이름입니다. -- `options.baseURL`는 로컬 서버의 엔드포인트입니다. -- `models`는 모델 ID를 구성하는 맵입니다. 모델 이름은 모델 선택 목록에 표시됩니다. +- `llama.cpp`는 사용자 정의 공급자 ID입니다. 원하는 문자열로 지정할 수 있습니다. +- `npm`은 이 공급자에 사용할 패키지를 지정합니다. 여기서는 OpenAI 호환 API를 위해 `@ai-sdk/openai-compatible`을 사용합니다. +- `name`은 UI에 표시될 공급자 이름입니다. +- `options.baseURL`은 로컬 서버의 엔드포인트입니다. +- `models`는 모델 ID와 해당 구성을 매핑합니다. 모델 이름은 모델 선택 목록에 표시됩니다. --- -###### IO.NET +### IO.NET IO.NET은 다양한 사용 사례에 최적화된 17개의 모델을 제공합니다: -1. [IO.NET 콘솔](https://ai.io.net/)에 머리, 계정을 만들고 API 키를 생성합니다. +1. [IO.NET 콘솔](https://ai.io.net/)로 이동하여 계정을 만들고 API 키를 생성합니다. -2. `/connect` 명령을 실행하고 **IO.NET**를 검색하십시오. +2. `/connect` 명령을 실행하고 **IO.NET**을 검색하십시오. ```txt /connect @@ -1115,7 +1133,7 @@ IO.NET은 다양한 사용 사례에 최적화된 17개의 모델을 제공합 ### LM Studio -LM Studio를 통해 로컬 모델을 사용할 수 있습니다. +LM Studio를 통해 로컬 모델을 사용하도록 구성할 수 있습니다. ```json title="opencode.json" "lmstudio" {5, 6, 8, 10-14} { @@ -1139,19 +1157,19 @@ LM Studio를 통해 로컬 모델을 사용할 수 있습니다. 이 예제에서: -- `lmstudio`는 주문 공급자 ID입니다. 원하는 문자열이 될 수 있습니다. -- `npm`는 이 공급자를 위해 사용할 포장을 지정합니다. 여기, `@ai-sdk/openai-compatible`는 OpenAI 호환 API에 사용됩니다. -- `name`는 UI에 있는 공급자를 위한 전시 이름입니다. -- `options.baseURL`는 로컬 서버의 엔드포인트입니다. -- `models`는 모델 ID를 구성하는 맵입니다. 모델 이름은 모델 선택 목록에 표시됩니다. +- `lmstudio`는 사용자 정의 공급자 ID입니다. 원하는 문자열로 지정할 수 있습니다. +- `npm`은 이 공급자에 사용할 패키지를 지정합니다. 여기서는 OpenAI 호환 API를 위해 `@ai-sdk/openai-compatible`을 사용합니다. +- `name`은 UI에 표시될 공급자 이름입니다. +- `options.baseURL`은 로컬 서버의 엔드포인트입니다. +- `models`는 모델 ID와 해당 구성을 매핑합니다. 모델 이름은 모델 선택 목록에 표시됩니다. --- -## Moonshot AI +### Moonshot AI -Moonshot AI에서 Kimi K2 사용 : +Moonshot AI에서 Kimi K2를 사용하려면: -1. [Moonshot AI 콘솔](https://platform.moonshot.ai/console)에 머리, 계정을 만들고, ** API 키**를 클릭합니다. +1. [Moonshot AI 콘솔](https://platform.moonshot.ai/console)로 이동하여 계정을 만들고 **Create API key**를 클릭합니다. 2. `/connect` 명령을 실행하고 **Moonshot AI**를 검색하십시오. @@ -1168,7 +1186,7 @@ Moonshot AI에서 Kimi K2 사용 : └ enter ``` -4. `/models` 명령을 실행하여 Kimi K2 . +4. `/models` 명령을 실행하여 *Kimi K2*를 선택하십시오. ```txt /models @@ -1176,9 +1194,9 @@ Moonshot AI에서 Kimi K2 사용 : --- -## MiniMax +### MiniMax -1. [MiniMax API 콘솔](https://platform.minimax.io/login)에 머리, 계정을 만들고 API 키를 생성합니다. +1. [MiniMax API 콘솔](https://platform.minimax.io/login)로 이동하여 계정을 만들고 API 키를 생성합니다. 2. `/connect` 명령을 실행하고 **MiniMax**를 검색하십시오. @@ -1195,7 +1213,7 @@ Moonshot AI에서 Kimi K2 사용 : └ enter ``` -4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 M2.1 . +4. `/models` 명령을 실행하여 모델(예: _M2.1_)을 선택하십시오. ```txt /models @@ -1203,9 +1221,9 @@ Moonshot AI에서 Kimi K2 사용 : --- -## Nebius Token Factory +### Nebius Token Factory -1. [Nebius Token Factory 콘솔](https://tokenfactory.nebius.com/)에 머리, 계정을 만들고, ** 키 추가 **. +1. [Nebius Token Factory 콘솔](https://tokenfactory.nebius.com/)로 이동하여 계정을 만들고 **Add Key**를 클릭합니다. 2. `/connect` 명령을 실행하고 **Nebius Token Factory**를 검색하십시오. @@ -1213,7 +1231,7 @@ Moonshot AI에서 Kimi K2 사용 : /connect ``` -3. Nebius 토큰 공장 API 키를 입력하십시오. +3. Nebius Token Factory API 키를 입력하십시오. ```txt ┌ API key @@ -1222,7 +1240,7 @@ Moonshot AI에서 Kimi K2 사용 : └ enter ``` -4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 Kimi K2 Instruct . +4. `/models` 명령을 실행하여 모델(예: _Kimi K2 Instruct_)을 선택하십시오. ```txt /models @@ -1230,12 +1248,12 @@ Moonshot AI에서 Kimi K2 사용 : --- -#### Ollama +### Ollama -Ollama를 통해 로컬 모델을 사용할 수 있습니다. +Ollama를 통해 로컬 모델을 사용하도록 구성할 수 있습니다. :::tip -Ollama는 opencode를 자동으로 구성할 수 있습니다. 자세한 내용은 [Ollama 통합 문서](https://docs.ollama.com/integrations/opencode)를 참조하십시오. +Ollama는 OpenCode에 대해 자동으로 구성될 수 있습니다. 자세한 내용은 [Ollama 통합 문서](https://docs.ollama.com/integrations/opencode)를 참조하십시오. ::: ```json title="opencode.json" "ollama" {5, 6, 8, 10-14} @@ -1260,35 +1278,35 @@ Ollama는 opencode를 자동으로 구성할 수 있습니다. 자세한 내용 이 예제에서: -- `ollama`는 주문 공급자 ID입니다. 원하는 문자열이 될 수 있습니다. -- `npm`는 이 공급자를 위해 사용할 포장을 지정합니다. 여기, `@ai-sdk/openai-compatible`는 OpenAI 호환 API에 사용됩니다. -- `name`는 UI에 있는 공급자를 위한 전시 이름입니다. -- `options.baseURL`는 로컬 서버의 엔드포인트입니다. -- `models`는 모델 ID를 구성하는 맵입니다. 모델 이름은 모델 선택 목록에 표시됩니다. +- `ollama`는 사용자 정의 공급자 ID입니다. 원하는 문자열로 지정할 수 있습니다. +- `npm`은 이 공급자에 사용할 패키지를 지정합니다. 여기서는 OpenAI 호환 API를 위해 `@ai-sdk/openai-compatible`을 사용합니다. +- `name`은 UI에 표시될 공급자 이름입니다. +- `options.baseURL`은 로컬 서버의 엔드포인트입니다. +- `models`는 모델 ID와 해당 구성을 매핑합니다. 모델 이름은 모델 선택 목록에 표시됩니다. :::tip -도구 호출이 작동하지 않는 경우, Ollama에서 `num_ctx` 증가. 주위 시작 16k - 32k. +도구 호출이 작동하지 않는 경우, Ollama에서 `num_ctx`를 늘려보십시오. 16k - 32k 정도에서 시작하십시오. ::: --- -## Ollama Cloud +### Ollama Cloud -opencode로 Ollama Cloud를 사용하려면: +OpenCode로 Ollama Cloud를 사용하려면: -1. [https://ollama.com/](https://ollama.com/) 이상 머리와 로그인하거나 계정을 만들 수 있습니다. +1. [https://ollama.com/](https://ollama.com/)으로 이동하여 로그인하거나 계정을 만듭니다. -2. Navigate to**Settings** > **Keys** 및 click **API Key**를 추가하여 새로운 API 키 생성. +2. **Settings** > **Keys**로 이동하여 **Add API Key**를 클릭해 새 API 키를 생성합니다. -3. opencode에서 사용을 위한 API 열쇠를 복사하십시오. +3. OpenCode에서 사용할 API 키를 복사합니다. -4. `/connect` 명령을 실행하고 ** Ollama Cloud**를 검색하십시오. +4. `/connect` 명령을 실행하고 **Ollama Cloud**를 검색하십시오. ```txt /connect ``` -5. Ollama Cloud API 키 입력. +5. Ollama Cloud API 키를 입력하십시오. ```txt ┌ API key @@ -1297,7 +1315,7 @@ opencode로 Ollama Cloud를 사용하려면: └ enter ``` -6. ** 중요 **: opencode의 클라우드 모델을 사용하기 전에, 로컬 모델 정보를 끌어야 합니다: +6. **중요**: OpenCode에서 클라우드 모델을 사용하기 전에, 로컬에서 모델 정보를 가져와야 합니다: ```bash ollama pull gpt-oss:20b-cloud @@ -1315,14 +1333,13 @@ opencode로 Ollama Cloud를 사용하려면: [ChatGPT Plus 또는 Pro](https://chatgpt.com/pricing)에 가입하는 것이 좋습니다. -1. 가입하면 `/connect` 명령을 실행하고 OpenAI를 선택하십시오. +1. 가입 후 `/connect` 명령을 실행하고 OpenAI를 선택하십시오. ```txt /connect ``` -2. **ChatGPT Plus/Pro** 옵션을 선택하고 브라우저를 열 수 있습니다. - 자주 묻는 질문 +2. **ChatGPT Plus/Pro** 옵션을 선택하면 브라우저가 열리고 인증을 요청합니다. ```txt ┌ Select auth method @@ -1332,7 +1349,7 @@ opencode로 Ollama Cloud를 사용하려면: └ ``` -3. 이제 모든 OpenAI 모델은 `/models` 명령을 사용할 때 사용할 수 있어야합니다. +3. 이제 `/models` 명령을 사용할 때 모든 OpenAI 모델을 사용할 수 있습니다. ```txt /models @@ -1340,23 +1357,23 @@ opencode로 Ollama Cloud를 사용하려면: ##### API 키 사용 -API 키가 이미 있다면 ** 수동으로 API 키**를 입력하고 terminal에서 붙여넣을 수 있습니다. +이미 API 키가 있다면 **Manually enter API Key**를 선택하고 터미널에 붙여넣을 수 있습니다. --- -## OpenCode Zen +### OpenCode Zen -OpenCode Zen은 opencode 팀에서 제공하는 테스트 및 검증된 모델 목록입니다. [더 알아보기](/docs/zen). +OpenCode Zen은 OpenCode 팀에서 제공하는 테스트 및 검증된 모델 목록입니다. [더 알아보기](/docs/zen). -1. 로그인 **OpenCode Zen** and click**Create API Key**. +1. **OpenCode Zen**에 로그인하고 **Create API Key**를 클릭합니다. -2. `/connect` 명령을 실행하고 **OpenCode Zen**를 검색하십시오. +2. `/connect` 명령을 실행하고 **OpenCode Zen**을 검색하십시오. ```txt /connect ``` -3. opencode API 키를 입력하십시오. +3. OpenCode API 키를 입력하십시오. ```txt ┌ API key @@ -1365,7 +1382,7 @@ OpenCode Zen은 opencode 팀에서 제공하는 테스트 및 검증된 모델 └ enter ``` -4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 Qwen 3 Coder 480B . +4. `/models` 명령을 실행하여 모델(예: _Qwen 3 Coder 480B_)을 선택하십시오. ```txt /models @@ -1373,9 +1390,9 @@ OpenCode Zen은 opencode 팀에서 제공하는 테스트 및 검증된 모델 --- -## OpenRouter +### OpenRouter -1. [OpenRouter 대시보드](https://openrouter.ai/settings/keys)에 머리, click ** API Key**를 클릭하고 키를 복사합니다. +1. [OpenRouter 대시보드](https://openrouter.ai/settings/keys)로 이동하여 **Create API Key**를 클릭하고 키를 복사합니다. 2. `/connect` 명령을 실행하고 OpenRouter를 검색하십시오. @@ -1383,7 +1400,7 @@ OpenCode Zen은 opencode 팀에서 제공하는 테스트 및 검증된 모델 /connect ``` -3. 공급자를 위한 API 열쇠를 입력하십시오. +3. API 키를 입력하십시오. ```txt ┌ API key @@ -1392,28 +1409,28 @@ OpenCode Zen은 opencode 팀에서 제공하는 테스트 및 검증된 모델 └ enter ``` -4. 많은 OpenRouter 모델은 기본적으로 `/models` 명령을 실행하여 원하는 것을 선택합니다. +4. 많은 OpenRouter 모델은 기본적으로 미리 로드되어 있으므로 `/models` 명령을 실행하여 원하는 것을 선택하십시오. ```txt /models ``` -opencode config를 통해 추가 모델을 추가할 수 있습니다. + OpenCode 구성을 통해 모델을 추가할 수도 있습니다. -```json title="opencode.json" {6} -{ - "$schema": "https://opencode.ai/config.json", - "provider": { - "openrouter": { - "models": { - "somecoolnewmodel": {} - } - } - } -} -``` + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` -5. 당신은 또한 당신의 opencode config를 통해 그들을 주문을 받아서 만들 수 있습니다. 공급자 지정의 예입니다. +5. 또한 OpenCode 구성을 통해 사용자 정의할 수도 있습니다. 다음은 공급자 순서를 지정하는 예입니다. ```json title="opencode.json" { @@ -1439,12 +1456,12 @@ opencode config를 통해 추가 모델을 추가할 수 있습니다. ### SAP AI Core -SAP AI Core는 OpenAI, Anthropic, Google, Amazon, Meta, Mistral 및 AI21의 40+ 모델에 대한 액세스를 제공합니다. +SAP AI Core는 OpenAI, Anthropic, Google, Amazon, Meta, Mistral 및 AI21의 40개 이상의 모델에 대한 액세스를 제공합니다. -1. [SAP BTP Cockpit](https://account.hana.ondemand.com/)로 이동하여 SAP AI Core 서비스 인스턴스로 이동하고 서비스 키를 만듭니다. +1. [SAP BTP Cockpit](https://account.hana.ondemand.com/)으로 이동하여 SAP AI Core 서비스 인스턴스로 이동하고 서비스 키를 만듭니다. :::tip - 서비스 키는 `clientid`, `clientsecret`, `url` 및 `serviceurls.AI_API_URL`를 포함하는 JSON 객체입니다. **Services** > **Instances 및 Subscriptions** 아래 AI Core 인스턴스를 찾을 수 있습니다. + 서비스 키는 `clientid`, `clientsecret`, `url` 및 `serviceurls.AI_API_URL`을 포함하는 JSON 객체입니다. **Services** > **Instances and Subscriptions** 아래에서 AI Core 인스턴스를 찾을 수 있습니다. ::: 2. `/connect` 명령을 실행하고 **SAP AI Core**를 검색하십시오. @@ -1462,29 +1479,29 @@ SAP AI Core는 OpenAI, Anthropic, Google, Amazon, Meta, Mistral 및 AI21의 40+ └ enter ``` -또는 `AICORE_SERVICE_KEY` 환경 변수를 설정: + 또는 `AICORE_SERVICE_KEY` 환경 변수를 설정합니다: -```bash + ```bash AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode -``` + ``` -또는 bash 프로파일에 추가: + 또는 bash 프로필에 추가합니다: -```bash title="~/.bash_profile" + ```bash title="~/.bash_profile" export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' -``` + ``` -4. 선택적으로 배치 ID 및 자원 그룹: +4. 선택적으로 배포 ID 및 리소스 그룹을 설정합니다: ```bash AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode ``` :::note - 이 설정은 선택 사항이며 SAP AI Core 설정에 따라 구성해야합니다. + 이 설정은 선택 사항이며 SAP AI Core 설정에 따라 구성해야 합니다. ::: -5. `/models` 명령을 실행하여 40+ 유효한 모형에서 선택하십시오. +5. `/models` 명령을 실행하여 40개 이상의 사용 가능한 모델 중에서 선택하십시오. ```txt /models @@ -1492,11 +1509,44 @@ SAP AI Core는 OpenAI, Anthropic, Google, Amazon, Meta, Mistral 및 AI21의 40+ --- -### OVHcloud AI 엔드포인트 +### STACKIT -1. [OVHcloud 패널](https://ovh.com/manager)에 머리. `Public Cloud` 섹션으로 이동, `AI & Machine Learning` > `AI Endpoints` 및 `API Keys` 탭에서, ** 새로운 API 키 활성화 **. +STACKIT AI Model Serving은 Llama, Mistral, Qwen과 같은 LLM에 초점을 맞추고 유럽 인프라에서 데이터 주권을 최대한 보장하는 완전 관리형 AI 모델 호스팅 환경을 제공합니다. -2. `/connect` 명령을 실행하고 ** OVHcloud AI Endpoints**를 검색하십시오. +1. [STACKIT Portal](https://portal.stackit.cloud)로 이동하여 **AI Model Serving**으로 이동한 다음 프로젝트의 인증 토큰을 만듭니다. + + :::tip + 인증 토큰을 만들기 전에 STACKIT 고객 계정, 사용자 계정 및 프로젝트가 필요합니다. + ::: + +2. `/connect` 명령을 실행하고 **STACKIT**을 검색하십시오. + + ```txt + /connect + ``` + +3. STACKIT AI Model Serving 인증 토큰을 입력하십시오. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. `/models` 명령을 실행하여 _Qwen3-VL 235B_ 또는 *Llama 3.3 70B*와 같은 사용 가능한 모델을 선택하십시오. + + ```txt + /models + ``` + +--- + +### OVHcloud AI Endpoints + +1. [OVHcloud 패널](https://ovh.com/manager)로 이동합니다. `Public Cloud` 섹션으로 이동하여 `AI & Machine Learning` > `AI Endpoints`로 간 뒤 `API Keys` 탭에서 **Create a new API key**를 클릭합니다. + +2. `/connect` 명령을 실행하고 **OVHcloud AI Endpoints**를 검색하십시오. ```txt /connect @@ -1511,7 +1561,7 @@ SAP AI Core는 OpenAI, Anthropic, Google, Amazon, Meta, Mistral 및 AI21의 40+ └ enter ``` -4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 gpt-oss-120b . +4. `/models` 명령을 실행하여 모델(예: _gpt-oss-120b_)을 선택하십시오. ```txt /models @@ -1521,9 +1571,9 @@ SAP AI Core는 OpenAI, Anthropic, Google, Amazon, Meta, Mistral 및 AI21의 40+ ### Scaleway -opencode를 사용하여 [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/)를 사용하려면: +OpenCode로 [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/)를 사용하려면: -1. [Scaleway 콘솔 IAM 설정](https://console.scaleway.com/iam/api-keys)를 통해 새로운 API 키 생성. +1. [Scaleway Console IAM 설정](https://console.scaleway.com/iam/api-keys)에서 새 API 키를 생성합니다. 2. `/connect` 명령을 실행하고 **Scaleway**를 검색하십시오. @@ -1540,7 +1590,7 @@ opencode를 사용하여 [Scaleway Generative APIs](https://www.scaleway.com/en/ └ enter ``` -4. `/models` 명령을 실행하여 같은 모델을 선택하십시오. devstral-2-123b-instruct-2512 또는 gpt-oss-120b . +4. `/models` 명령을 실행하여 모델(예: _devstral-2-123b-instruct-2512_ 또는 _gpt-oss-120b_)을 선택하십시오. ```txt /models @@ -1548,9 +1598,9 @@ opencode를 사용하여 [Scaleway Generative APIs](https://www.scaleway.com/en/ --- -## Together AI +### Together AI -1. [Together AI 콘솔](https://api.together.ai)에 머리, 계정을 만들고 ** 키 추가 **를 클릭합니다. +1. [Together AI 콘솔](https://api.together.ai)로 이동하여 계정을 만들고 **Add Key**를 클릭합니다. 2. `/connect` 명령을 실행하고 **Together AI**를 검색하십시오. @@ -1558,7 +1608,7 @@ opencode를 사용하여 [Scaleway Generative APIs](https://www.scaleway.com/en/ /connect ``` -3. 함께 AI API 키를 입력하십시오. +3. Together AI API 키를 입력하십시오. ```txt ┌ API key @@ -1567,7 +1617,7 @@ opencode를 사용하여 [Scaleway Generative APIs](https://www.scaleway.com/en/ └ enter ``` -4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 Kimi K2 Instruct . +4. `/models` 명령을 실행하여 모델(예: _Kimi K2 Instruct_)을 선택하십시오. ```txt /models @@ -1575,17 +1625,17 @@ opencode를 사용하여 [Scaleway Generative APIs](https://www.scaleway.com/en/ --- -## Venice AI +### Venice AI -1. [Venice AI 콘솔](https://venice.ai)에 머리, 계정을 만들고 API 키를 생성합니다. +1. [Venice AI 콘솔](https://venice.ai)로 이동하여 계정을 만들고 API 키를 생성합니다. -2. `/connect` 명령을 실행하고 **Venice AI **를 검색하십시오. +2. `/connect` 명령을 실행하고 **Venice AI**를 검색하십시오. ```txt /connect ``` -3. 베니스 AI API 열쇠를 입력하십시오. +3. Venice AI API 키를 입력하십시오. ```txt ┌ API key @@ -1594,7 +1644,7 @@ opencode를 사용하여 [Scaleway Generative APIs](https://www.scaleway.com/en/ └ enter ``` -4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 Llama 3.3 70B . +4. `/models` 명령을 실행하여 모델(예: _Llama 3.3 70B_)을 선택하십시오. ```txt /models @@ -1602,11 +1652,11 @@ opencode를 사용하여 [Scaleway Generative APIs](https://www.scaleway.com/en/ --- -## Vercel AI 게이트웨이 +### Vercel AI Gateway -Vercel AI를 게이트웨이는 OpenAI, Anthropic, Google, xAI 등에서 모델에 액세스할 수 있습니다. 모델은 Markup없이 목록 가격에서 제공됩니다. +Vercel AI Gateway는 OpenAI, Anthropic, Google, xAI 등의 모델에 액세스할 수 있으며, 통합된 엔드포인트를 통해 더 많은 기능을 제공합니다. 모델은 마크업 없이 정가로 제공됩니다. -1. [Vercel 대시보드](https://vercel.com/)에 머리, **AI Gateway** 탭으로 이동하고, **API 키**를 클릭하여 새로운 API 키 생성. +1. [Vercel 대시보드](https://vercel.com/)로 이동하여 **AI Gateway** 탭으로 간 뒤, **API keys**를 클릭하여 새 API 키를 생성합니다. 2. `/connect` 명령을 실행하고 **Vercel AI Gateway**를 검색하십시오. @@ -1614,7 +1664,7 @@ Vercel AI를 게이트웨이는 OpenAI, Anthropic, Google, xAI 등에서 모델 /connect ``` -3. Vercel AI Gateway API 키 입력. +3. Vercel AI Gateway API 키를 입력하십시오. ```txt ┌ API key @@ -1623,13 +1673,13 @@ Vercel AI를 게이트웨이는 OpenAI, Anthropic, Google, xAI 등에서 모델 └ enter ``` -4. 모델을 선택하려면 `/models` 명령을 실행하십시오. +4. `/models` 명령을 실행하여 모델을 선택하십시오. ```txt /models ``` -opencode config를 통해 모델을 사용자 정의 할 수 있습니다. 공급자 routing 순서를 지정하는 예입니다. +OpenCode 구성을 통해 모델을 사용자 정의할 수도 있습니다. 다음은 공급자 라우팅 순서를 지정하는 예입니다. ```json title="opencode.json" { @@ -1648,19 +1698,19 @@ opencode config를 통해 모델을 사용자 정의 할 수 있습니다. 공 } ``` -몇몇 유용한 여정 선택권: +몇 가지 유용한 라우팅 옵션: | 옵션 | 설명 | | ------------------- | --------------------------------- | -| `order` | 공급자의 순서 | -| `only` | 특정 공급자 제한 | -| `zeroDataRetention` | 제로 데이터 보유 정책만 이용 가능 | +| `order` | 시도할 공급자 순서 | +| `only` | 특정 공급자로 제한 | +| `zeroDataRetention` | 데이터 보유 정책이 없는 곳만 사용 | --- ### xAI -1. [xAI 콘솔](https://console.x.ai/)에 머리, 계정을 만들고 API 키를 생성합니다. +1. [xAI 콘솔](https://console.x.ai/)로 이동하여 계정을 만들고 API 키를 생성합니다. 2. `/connect` 명령을 실행하고 **xAI**를 검색하십시오. @@ -1677,7 +1727,7 @@ opencode config를 통해 모델을 사용자 정의 할 수 있습니다. 공 └ enter ``` -4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 Grok Beta . +4. `/models` 명령을 실행하여 모델(예: _Grok Beta_)을 선택하십시오. ```txt /models @@ -1687,15 +1737,15 @@ opencode config를 통해 모델을 사용자 정의 할 수 있습니다. 공 ### Z.AI -1. [Z.AI API 콘솔](https://z.ai/manage-apikey/apikey-list)에 머리, 계정을 만들고, **새로운 API 키**를 클릭합니다. +1. [Z.AI API 콘솔](https://z.ai/manage-apikey/apikey-list)로 이동하여 계정을 만들고 **Create a new API key**를 클릭합니다. -2. `/connect` 명령을 실행하고 ** Z.AI**를 검색하십시오. +2. `/connect` 명령을 실행하고 **Z.AI**를 검색하십시오. ```txt /connect ``` -**GLM 코딩 플랜**에 가입하면 **Z.AI 코딩 플랜**을 선택하십시오. + **GLM Coding Plan**에 가입했다면 **Z.AI Coding Plan**을 선택하십시오. 3. Z.AI API 키를 입력하십시오. @@ -1706,7 +1756,7 @@ opencode config를 통해 모델을 사용자 정의 할 수 있습니다. 공 └ enter ``` -4. `/models` 명령을 실행하여 같은 모델을 선택하십시오 GLM-4.7 . +4. `/models` 명령을 실행하여 모델(예: _GLM-4.7_)을 선택하십시오. ```txt /models @@ -1714,9 +1764,9 @@ opencode config를 통해 모델을 사용자 정의 할 수 있습니다. 공 --- -## ZenMux +### ZenMux -1. [ZenMux 대쉬보드](https://zenmux.ai/settings/keys)에 머리, click **Create API Key**, 키 복사. +1. [ZenMux 대시보드](https://zenmux.ai/settings/keys)로 이동하여 **Create API Key**를 클릭하고 키를 복사합니다. 2. `/connect` 명령을 실행하고 ZenMux를 검색하십시오. @@ -1724,7 +1774,7 @@ opencode config를 통해 모델을 사용자 정의 할 수 있습니다. 공 /connect ``` -3. 공급자를 위한 API 열쇠를 입력하십시오. +3. API 키를 입력하십시오. ```txt ┌ API key @@ -1733,38 +1783,38 @@ opencode config를 통해 모델을 사용자 정의 할 수 있습니다. 공 └ enter ``` -4. 많은 ZenMux 모델은 기본적으로 사전 로드되며 `/models` 명령을 실행하여 원하는 것을 선택합니다. +4. 많은 ZenMux 모델은 기본적으로 미리 로드되어 있으므로 `/models` 명령을 실행하여 원하는 것을 선택하십시오. ```txt /models ``` -opencode config를 통해 추가 모델을 추가할 수 있습니다. + OpenCode 구성을 통해 모델을 추가할 수도 있습니다. -```json title="opencode.json" {6} -{ - "$schema": "https://opencode.ai/config.json", - "provider": { - "zenmux": { - "models": { - "somecoolnewmodel": {} - } - } - } -} -``` + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` --- ## 사용자 정의 공급자 -`/connect` 명령에 나열되지 않은 **OpenAI-compatible** 공급자를 추가하려면: +`/connect` 명령에 나열되지 않은 **OpenAI 호환** 공급자를 추가하려면: :::tip -opencode를 사용하여 OpenAI 호환 공급자를 사용할 수 있습니다. 가장 현대적인 AI 제공 업체는 OpenAI 호환 API를 제공합니다. +OpenCode에서 모든 OpenAI 호환 공급자를 사용할 수 있습니다. 대부분의 최신 AI 공급자는 OpenAI 호환 API를 제공합니다. ::: -1. `/connect` 명령을 실행하고 ** 다른**로 스크롤하십시오. +1. `/connect` 명령을 실행하고 **Other**로 스크롤하십시오. ```bash $ /connect @@ -1777,7 +1827,7 @@ opencode를 사용하여 OpenAI 호환 공급자를 사용할 수 있습니다. └ ``` -2. 공급자를 위한 유일한 ID를 입력하십시오. +2. 공급자를 위한 고유한 ID를 입력하십시오. ```bash $ /connect @@ -1790,10 +1840,10 @@ opencode를 사용하여 OpenAI 호환 공급자를 사용할 수 있습니다. ``` :::note - 기억에 남는 ID를 선택하면 구성 파일에서 이것을 사용할 수 있습니다. + 기억하기 쉬운 ID를 선택하십시오. 구성 파일에서 이 ID를 사용하게 됩니다. ::: -3. 공급자를 위한 당신의 API 열쇠를 입력하십시오. +3. 공급자의 API 키를 입력하십시오. ```bash $ /connect @@ -1829,23 +1879,23 @@ opencode를 사용하여 OpenAI 호환 공급자를 사용할 수 있습니다. } ``` -여기에 구성 옵션: + 구성 옵션은 다음과 같습니다: + - **npm**: 사용할 AI SDK 패키지. OpenAI 호환 공급자의 경우 `@ai-sdk/openai-compatible` + - **name**: UI에 표시될 이름 + - **models**: 사용 가능한 모델 + - **options.baseURL**: API 엔드포인트 URL + - **options.apiKey**: 인증을 사용하지 않는 경우 선택적으로 API 키 설정 + - **options.headers**: 선택적으로 사용자 정의 헤더 설정 -- **npm**: AI SDK 패키지, OpenAI 호환 공급자 `@ai-sdk/openai-compatible` -**name**: UI의 표시 이름. -- ** 모델**: 유효한 모델. -- **options.baseURL**: API 엔드포인트 URL. -- **options.apiKey**: 선택적으로 auth를 사용하지 않는 경우 API 키 설정. -- **options.headers**: 선택적으로 사용자 정의 헤더를 설정합니다. + 고급 옵션에 대한 자세한 내용은 아래 예제를 참조하십시오. -아래 예에서 고급 옵션에 더. - -5. `/models` 명령을 실행하고 사용자 정의 공급자와 모델은 선택 목록에서 나타납니다. +5. `/models` 명령을 실행하면 사용자 정의 공급자와 모델이 선택 목록에 나타납니다. --- ##### 예제 -다음은 `apiKey`, `headers` 및 모델 `limit` 옵션 설정 예입니다. +다음은 `apiKey`, `headers` 및 모델 `limit` 옵션을 설정하는 예입니다. ```json title="opencode.json" {9,11,17-20} { @@ -1877,11 +1927,12 @@ opencode를 사용하여 OpenAI 호환 공급자를 사용할 수 있습니다. 구성 세부 사항: -- **apiKey**: `env` 변수 구문을 사용하여 설정, [learn more](/docs/config#env-vars). -**headers**: 각 요청으로 전송된 사용자 정의 헤더. -- **limit.context**: 모델이 허용하는 최대 Input Tokens. -- **limit.output**: 모델이 생성할 수 있는 최대 Output Tokens. +- **apiKey**: `env` 변수 구문을 사용하여 설정, [더 알아보기](/docs/config#env-vars). +- **headers**: 각 요청과 함께 전송되는 사용자 정의 헤더. +- **limit.context**: 모델이 허용하는 최대 입력 토큰. +- **limit.output**: 모델이 생성할 수 있는 최대 출력 토큰. -`limit` 필드를 사용하면 opencode가 얼마나 많은 컨텍스트를 이해 할 수 있습니다. 표준 공급자는 model.dev에서 자동적으로 당깁니다. +`limit` 필드를 사용하면 OpenCode가 남은 컨텍스트 양을 파악할 수 있습니다. 표준 공급자는 models.dev에서 자동으로 이를 가져옵니다. --- @@ -1889,13 +1940,11 @@ opencode를 사용하여 OpenAI 호환 공급자를 사용할 수 있습니다. 공급자 구성에 문제가 있는 경우 다음을 확인하십시오. -1. **주의 설정 확인 **: `opencode auth list`를 실행하여 자격 증명을 볼 수 있습니다. - 공급자는 config에 추가됩니다. +1. **인증 설정 확인**: `opencode auth list`를 실행하여 공급자의 자격 증명이 구성에 추가되었는지 확인하십시오. -이것은 Amazon Bedrock과 같은 공급자에 적용되지 않습니다. 환경 변수에 의존합니다. + Amazon Bedrock과 같이 인증을 위해 환경 변수에 의존하는 공급자에는 적용되지 않습니다. -2. 주문 공급자를 위해, opencode config를 검사하고: - -- `/connect` 명령에 사용되는 공급자 ID가 opencode config에서 ID를 일치시킵니다. -- 오른쪽 npm 패키지는 공급자에 사용됩니다. 예를 들어 Cerebras의 `@ai-sdk/cerebras`를 사용합니다. 그리고 다른 모든 OpenAI 호환 공급자를 위해, 사용 `@ai-sdk/openai-compatible`. -- 올바른 API 엔드포인트는 `options.baseURL` 필드에 사용됩니다. +2. 사용자 정의 공급자의 경우, OpenCode 구성을 확인하고 다음을 수행하십시오: + - `/connect` 명령에 사용된 공급자 ID가 OpenCode 구성의 ID와 일치하는지 확인하십시오. + - 공급자에 올바른 npm 패키지가 사용되었는지 확인하십시오. 예를 들어 Cerebras에는 `@ai-sdk/cerebras`를 사용하고, 다른 모든 OpenAI 호환 공급자에는 `@ai-sdk/openai-compatible`을 사용하십시오. + - `options.baseURL` 필드에 올바른 API 엔드포인트가 사용되었는지 확인하십시오. diff --git a/packages/web/src/content/docs/ko/sdk.mdx b/packages/web/src/content/docs/ko/sdk.mdx index f6d43c136d..a5d12d1ab0 100644 --- a/packages/web/src/content/docs/ko/sdk.mdx +++ b/packages/web/src/content/docs/ko/sdk.mdx @@ -117,13 +117,85 @@ try { --- +## 구조화된 출력 + +JSON 스키마와 함께 `format`을 지정하여 모델에서 구조화된 JSON 출력을 요청할 수 있습니다. 모델은 `StructuredOutput` 도구를 사용하여 스키마와 일치하는 검증된 JSON을 반환합니다. + +### 기본 사용법 + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Access the structured output +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### 출력 형식 유형 + +| 유형 | 설명 | +| ------------- | ------------------------------------------------- | +| `text` | 기본값. 표준 텍스트 응답 (구조화된 출력 없음) | +| `json_schema` | 제공된 스키마와 일치하는 검증된 JSON을 반환합니다 | + +### JSON 스키마 형식 + +`type: 'json_schema'`를 사용할 때 다음을 제공하십시오: + +| 필드 | 유형 | 설명 | +| ------------ | --------------- | ------------------------------------------- | +| `type` | `'json_schema'` | 필수. JSON 스키마 모드를 지정합니다 | +| `schema` | `object` | 필수. 출력 구조를 정의하는 JSON 스키마 객체 | +| `retryCount` | `number` | 선택 사항. 검증 재시도 횟수 (기본값: 2) | + +### 오류 처리 + +모델이 모든 재시도 후에도 유효한 구조화된 출력을 생성하지 못하면 응답에 `StructuredOutputError`가 포함됩니다: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### 모범 사례 + +1. **명확한 설명 제공**: 모델이 추출할 데이터를 이해하는 데 도움이 되도록 스키마 속성에 명확한 설명을 제공하십시오. +2. **`required` 사용**: 필수 필드를 지정하려면 `required`를 사용하십시오. +3. **스키마를 집중적으로 유지**: 복잡한 중첩 스키마는 모델이 올바르게 채우기 더 어려울 수 있습니다. +4. **적절한 `retryCount` 설정**: 복잡한 스키마의 경우 늘리고 단순한 스키마의 경우 줄이십시오. + +--- + ## API SDK는 type-safe 클라이언트를 통해 모든 서버 API를 노출합니다. --- -## 글로벌 +### 글로벌 | 메서드 | 설명 | 응답 | | ----------------- | ---------------------- | ------------------------------------ | @@ -142,10 +214,10 @@ console.log(health.data.version) ### 앱 -| 방법 | 설명 | 응답 | -| -------------- | ------------------------- | ----------------------------------------------- | -| `app.log()` | 로그 항목 작성 | `boolean` | -| `app.agents()` | 이용 가능한 모든 에이전트 | 에이전트[] | +| 방법 | 설명 | 응답 | +| -------------- | ------------------------- | ------------------------------------------- | +| `app.log()` | 로그 항목 작성 | `boolean` | +| `app.agents()` | 이용 가능한 모든 에이전트 | Agent[] | --- @@ -167,7 +239,7 @@ const agents = await client.app.agents() --- -## 프로젝트 +### 프로젝트 | 방법 | 설명 | 응답 | | ------------------- | ----------------------- | --------------------------------------------- | @@ -205,7 +277,7 @@ const pathInfo = await client.path.get() --- -#### 구성 +### 구성 | 방법 | 설명 | 응답 | | -------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------- | @@ -224,29 +296,29 @@ const { providers, default: defaults } = await client.config.providers() --- -## 세션 +### 세션 -| 메서드 | 설명 | 비고 | -| ---------------------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | 세션 일람 | Session[] | -| `session.get({ path })` | 세션 가져 오기 | Session | -| `session.children({ path })` | 하위 세션 목록 | 반품 Session | -| `session.create({ body })` | 세션 만들기 | 리턴 Session | -| `session.delete({ path })` | 세션 삭제 | `boolean` 반품 | -| `session.update({ path, body })` | 업데이트 세션 속성 | 반품 Session | -| `session.init({ path, body })` | 앱 초기화 및 `AGENTS.md` 분석 | `boolean`를 반환 | -| `session.abort({ path })` | 운영 중인 세션 | 반품 `boolean` | -| `session.share({ path })` | 공유 세션 | 반품 Session | -| `session.unshare({ path })` | 공유 세션 | 반품 Session | -| `session.summarize({ path, body })` | 세션 요약 | 반품 `boolean` | -| `session.messages({ path })` | 세션의 메시지 목록 | `{ info: `Message`, parts: `Part`}[]` | -| `session.message({ path })` | 메시지 상세정보 | 반품 `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | prompt 메시지 보내기 | `body.noReply: true` 반환 UserMessage (콘텍스트 전용). 기본 반환 AssistantMessage 에 AI 응답 | -| `session.command({ path, body })` | 세션으로 명령을 전송 | `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | shell 명령을 실행 | AssistantMessage | -| `session.revert({ path, body })` | 메시지 다시 변환 | Session | -| `session.unrevert({ path })` | 메시지 되돌리기 취소 | 반품 Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | 허가 요청 대응 | 반품 `boolean` | +| 메서드 | 설명 | 비고 | +| ---------------------------------------------------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | 세션 일람 | Session[] | +| `session.get({ path })` | 세션 가져 오기 | Session | +| `session.children({ path })` | 하위 세션 목록 | 반품 Session | +| `session.create({ body })` | 세션 만들기 | 리턴 Session | +| `session.delete({ path })` | 세션 삭제 | `boolean` 반품 | +| `session.update({ path, body })` | 업데이트 세션 속성 | 반품 Session | +| `session.init({ path, body })` | 앱 초기화 및 `AGENTS.md` 분석 | `boolean`를 반환 | +| `session.abort({ path })` | 운영 중인 세션 | 반품 `boolean` | +| `session.share({ path })` | 공유 세션 | 반품 Session | +| `session.unshare({ path })` | 공유 세션 취소 | 반품 Session | +| `session.summarize({ path, body })` | 세션 요약 | 반품 `boolean` | +| `session.messages({ path })` | 세션의 메시지 목록 | `{ info: `Message`, parts: `Part`}[]` | +| `session.message({ path })` | 메시지 상세정보 | 반품 `{ info: `Message`, parts: `Part[]`}` | +| `session.prompt({ path, body })` | prompt 메시지 보내기 | `body.noReply: true`는 UserMessage(컨텍스트 전용)를 반환합니다. 기본값은 AI 응답과 함께 AssistantMessage를 반환합니다. [구조화된 출력](#구조화된-출력)을 위한 `body.outputFormat`을 지원합니다 | +| `session.command({ path, body })` | 세션으로 명령을 전송 | `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `session.shell({ path, body })` | shell 명령을 실행 | AssistantMessage | +| `session.revert({ path, body })` | 메시지 다시 변환 | Session | +| `session.unrevert({ path })` | 메시지 되돌리기 취소 | 반품 Session | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | 허가 요청 대응 | 반품 `boolean` | --- @@ -281,7 +353,7 @@ await client.session.prompt({ --- -## 파일 +### 파일 | 방법 | 설명 | 응답 | | ------------------------- | ---------------------------- | -------------------------------------------------------------------------------------- | @@ -322,7 +394,7 @@ const content = await client.file.read({ --- -#### TUI +### TUI | 방법 | 설명 | 응답 | | ------------------------------ | ------------------------ | --------- | @@ -353,7 +425,7 @@ await client.tui.showToast({ --- -##### 인증 +### 인증 | 방법 | 설명 | 응답 | | ------------------- | -------------- | --------- | @@ -372,7 +444,7 @@ await client.auth.set({ --- -## 이벤트 +### 이벤트 | 방법 | 설명 | 응답 | | ------------------- | ----------------------- | ----------------------- | diff --git a/packages/web/src/content/docs/ko/themes.mdx b/packages/web/src/content/docs/ko/themes.mdx index b83b620170..af148eda10 100644 --- a/packages/web/src/content/docs/ko/themes.mdx +++ b/packages/web/src/content/docs/ko/themes.mdx @@ -3,28 +3,27 @@ title: 테마 description: 내장 테마를 선택하거나 자신만의 테마를 정의하세요. --- -opencode를 사용하면 여러 내장 테마 중 하나에서 선택할 수 있으며 terminal 테마에 적응하는 테마를 사용하거나 사용자 정의 테마를 정의 할 수 있습니다. +OpenCode를 사용하면 여러 내장 테마 중 하나에서 선택할 수 있으며 terminal 테마에 적응하는 테마를 사용하거나 사용자 정의 테마를 정의 할 수 있습니다. -기본적으로 opencode는 자체 `opencode` 테마를 사용합니다. +기본적으로 OpenCode는 자체 `opencode` 테마를 사용합니다. --- ## 터미널 요구 사항 -자신의 풀 컬러 팔레트로 올바르게 표시하려면 terminal을 지원해야합니다 ** truecolor** (24 비트 색상). 대부분의 현대 terminal은 기본적으로 이것을 지원합니다, 그러나 당신은 그것을 가능하게 할 필요가 있을지도 모릅니다: +테마가 전체 색상 팔레트로 올바르게 표시되려면 터미널이 **truecolor** (24비트 색상)를 지원해야 합니다. 대부분의 최신 터미널은 기본적으로 이를 지원하지만, 활성화해야 할 수도 있습니다: --**체크 지원**: `echo $COLORTERM` - 그것은 `truecolor` 또는 `24bit`를 출력해야 합니다 +- **지원 확인**: `echo $COLORTERM` 실행 - `truecolor` 또는 `24bit`가 출력되어야 합니다. +- **truecolor 활성화**: 셸 프로필에서 환경 변수 `COLORTERM=truecolor`를 설정하십시오. +- **터미널 호환성**: 터미널 에뮬레이터가 24비트 색상을 지원하는지 확인하십시오 (iTerm2, Alacritty, Kitty, Windows Terminal 및 최신 버전의 GNOME Terminal 등 대부분의 최신 터미널이 지원함). -- ** truecolor 사용 가능**: shell 프로파일에서 환경 변수 `COLORTERM=truecolor`를 설정 -- **Terminal 호환성 **: terminal 에뮬레이터 지원 24 비트 색상 (iTerm2, Alacritty, Kitty, Windows Terminal 및 GNOME Terminal의 최신 버전) - -truecolor 지원 없이, 테마는 감소된 색깔 정확도로 나타날지도 모릅니다 또는 가장 가까운 256 색깔 대류로 뒤떨어질지도 모릅니다. +truecolor 지원이 없으면 테마가 감소된 색상 정확도로 표시되거나 가장 가까운 256색 근사치로 대체될 수 있습니다. --- ## 내장 테마 -opencode는 여러 내장 테마와 함께 제공됩니다. +OpenCode는 여러 내장 테마와 함께 제공됩니다. | 이름 | 설명 | | ---------------------- | ------------------------------------------------------------------- | @@ -46,27 +45,27 @@ opencode는 여러 내장 테마와 함께 제공됩니다. ## 시스템 테마 -`system` 테마는 terminal의 색깔 계획에 자동적으로 적응시키기 위하여 디자인됩니다. 고정 색상을 사용하는 전통적인 테마와 달리, system 테마: +`system` 테마는 터미널의 색상 스키마에 자동으로 적응하도록 설계되었습니다. 고정 색상을 사용하는 기존 테마와 달리, system 테마는: -- **그레이스케일**: terminal의 배경 색상을 기반으로 사용자 정의 회색 가늠자를 만들고 최적의 대조를 보장합니다. -- ** ANSI 색상 사용 ** : terminal의 색상 팔레트를 존중하는 구문 강조 및 UI 요소에 대한 표준 ANSI 색상 (0-15). -- ** terminal 기본 사항**: `none` 텍스트 및 배경 색상을 사용하여 terminal의 네이티브 외관을 유지합니다. +- **그레이스케일 생성**: 터미널의 배경 색상을 기반으로 사용자 정의 그레이스케일을 생성하여 최적의 대비를 보장합니다. +- **ANSI 색상 사용**: 구문 강조 및 UI 요소에 표준 ANSI 색상(0-15)을 활용하여 터미널의 색상 팔레트를 존중합니다. +- **터미널 기본값 유지**: 텍스트 및 배경 색상에 `none`을 사용하여 터미널의 기본 모양을 유지합니다. -시스템 테마는 사용자를위한 것입니다 : +시스템 테마는 다음과 같은 사용자에게 적합합니다: -- opencode가 terminal의 외관과 일치해야 합니다. -- 사용자 정의 terminal 색상 구성 -- 모든 terminal 응용 분야의 일관된 모습 +- OpenCode가 터미널의 모양과 일치하기를 원하는 경우 +- 사용자 정의 터미널 색상 스키마를 사용하는 경우 +- 모든 터미널 애플리케이션에서 일관된 모양을 선호하는 경우 --- ## 테마 사용 -테마를 `/theme` 명령어로 선택하여 테마를 선택할 수 있습니다. 또는 [config](/docs/config)에서 지정할 수 있습니다. +`/theme` 명령어로 테마 선택기를 불러와 테마를 선택할 수 있습니다. 또는 `tui.json`에서 지정할 수 있습니다. -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` @@ -75,32 +74,35 @@ opencode는 여러 내장 테마와 함께 제공됩니다. ## 사용자 정의 테마 -opencode는 사용자가 쉽게 테마를 만들 수 있도록 유연한 JSON 기반 테마 시스템을 지원합니다. +OpenCode는 사용자가 쉽게 테마를 만들고 사용자 정의할 수 있도록 유연한 JSON 기반 테마 시스템을 지원합니다. --- -##### 계층 구조 +### 계층 구조 -테마는 다음과 같은 순서에서 여러 디렉토리에서로드됩니다. 나중에 감독은 이전 것을 무시합니다. +테마는 다음 순서대로 여러 디렉토리에서 로드되며, 나중 디렉토리가 이전 디렉토리를 덮어씁니다: -1.**Built-in themes** - 이것은 바이너리에 내장되어 있습니다. 2. **사용자 설정 디렉토리 ** - `~/.config/opencode/themes/*.json` 또는 `$XDG_CONFIG_HOME/opencode/themes/*.json`에서 정의 3. ** 루트 디렉토리 ** - `/.opencode/themes/*.json`에서 정의 4. **현재 작업 디렉토리 ** - `./.opencode/themes/*.json`에서 정의 +1. **내장 테마 (Built-in themes)** - 바이너리에 내장되어 있습니다. +2. **사용자 설정 디렉토리 (User config directory)** - `~/.config/opencode/themes/*.json` 또는 `$XDG_CONFIG_HOME/opencode/themes/*.json`에 정의됩니다. +3. **프로젝트 루트 디렉토리 (Project root directory)** - `/.opencode/themes/*.json`에 정의됩니다. +4. **현재 작업 디렉토리 (Current working directory)** - `./.opencode/themes/*.json`에 정의됩니다. -여러 디렉토리가 같은 이름을 가진 테마를 포함한다면, 더 높은 우선 순위를 가진 디렉토리의 테마가 사용됩니다. +여러 디렉토리에 같은 이름의 테마가 있는 경우, 더 높은 우선 순위를 가진 디렉토리의 테마가 사용됩니다. --- ### 테마 만들기 -사용자 정의 테마를 만들려면 테마 디렉토리 중 하나에서 JSON 파일을 만듭니다. +사용자 정의 테마를 만들려면 테마 디렉토리 중 하나에 JSON 파일을 만듭니다. -사용자 넓은 테마: +사용자 전역 테마: ```bash no-frame mkdir -p ~/.config/opencode/themes vim ~/.config/opencode/themes/my-theme.json ``` -프로젝트 별 테마. +프로젝트별 테마: ```bash no-frame mkdir -p .opencode/themes @@ -111,35 +113,34 @@ vim .opencode/themes/my-theme.json ### JSON 형식 -테마는 유연한 JSON 형식을 사용하여 지원: +테마는 다음을 지원하는 유연한 JSON 형식을 사용합니다: --**Hex 색상**: `"#ffffff"` - -- ** ANSI 색상**: `3` (0-255) -- ** 색상 참조 ** : `"primary"` 또는 사용자 정의 정의 -- ** 어두운 / 조명 변형 ** : `{"dark": "#000", "light": "#fff"}` -- ** 색상 없음 ** : `"none"` - terminal의 기본 색상 또는 투명 사용 +- **Hex 색상**: `"#ffffff"` +- **ANSI 색상**: `3` (0-255) +- **색상 참조**: `"primary"` 또는 사용자 정의 정의 +- **다크/라이트 변형**: `{"dark": "#000", "light": "#fff"}` +- **색상 없음**: `"none"` - 터미널의 기본 색상 또는 투명 사용 --- ### 색상 정의 -`defs` 단면도는 선택적이고 당신은 주제에서 참조될 수 있는 재사용할 수 있는 색깔을 정의할 수 있습니다. +`defs` 섹션은 선택 사항이며 테마 내에서 참조할 수 있는 재사용 가능한 색상을 정의할 수 있습니다. --- -## 터미널 기본값 +### 터미널 기본값 -특별한 가치 `"none"`는 terminal의 기본 색깔을 상속하기 위하여 어떤 색깔든지를 위해 사용될 수 있습니다. 이것은 특히 당신의 terminal의 색깔 계획과 이음새가 없는 혼합 테마 창조를 위해 유용합니다: +`"none"`이라는 특별한 값은 모든 색상에 대해 터미널의 기본 색상을 상속하는 데 사용할 수 있습니다. 이는 특히 터미널의 색상 스키마와 매끄럽게 어우러지는 테마를 만들 때 유용합니다: -- `"text": "none"` - terminal의 기본 전경 색상 사용 -- `"background": "none"` - terminal의 기본 배경 색상 사용 +- `"text": "none"` - 터미널의 기본 전경색 사용 +- `"background": "none"` - 터미널의 기본 배경색 사용 --- ### 예제 -사용자 정의 테마의 예입니다 : +사용자 정의 테마의 예입니다: ```json title="my-theme.json" { diff --git a/packages/web/src/content/docs/ko/tui.mdx b/packages/web/src/content/docs/ko/tui.mdx index 8717cc785f..669d899d0c 100644 --- a/packages/web/src/content/docs/ko/tui.mdx +++ b/packages/web/src/content/docs/ko/tui.mdx @@ -5,9 +5,9 @@ description: OpenCode 터미널 사용자 인터페이스 사용. import { Tabs, TabItem } from "@astrojs/starlight/components" -opencode는 LLM과 함께 프로젝트를 위해 대화형 terminal 인터페이스 또는 TUI를 제공합니다. +OpenCode는 LLM과 함께 프로젝트 작업을 하기 위한 대화형 터미널 인터페이스(TUI)를 제공합니다. -opencode는 현재 디렉토리에 TUI를 시작합니다. +OpenCode를 실행하면 현재 디렉토리에서 TUI가 시작됩니다. ```bash opencode @@ -19,7 +19,7 @@ opencode opencode /path/to/project ``` -TUI에 있다면 메시지가 표시됩니다. +TUI에 들어가면 메시지를 입력하여 프롬프트할 수 있습니다. ```text Give me a quick summary of the codebase. @@ -29,10 +29,10 @@ Give me a quick summary of the codebase. ## 파일 참조 -`@`를 사용하여 메시지에 파일을 참조 할 수 있습니다. 이것은 현재 작업 디렉토리에서 fuzzy 파일 검색입니다. +`@`를 사용하여 메시지에서 파일을 참조할 수 있습니다. 이것은 현재 작업 디렉토리에서 퍼지(fuzzy) 파일 검색을 수행합니다. :::tip -`@`를 사용하여 메시지의 참조 파일을 사용할 수 있습니다. +`@`를 사용하여 메시지에서 파일을 참조할 수 있습니다. ::: ```text "@packages/functions/src/api/index.ts" @@ -45,7 +45,7 @@ How is auth handled in @packages/functions/src/api/index.ts? ## Bash 명령 -`!`를 사용하여 shell 명령을 실행합니다. +`!`로 메시지를 시작하여 셸 명령을 실행합니다. ```bash frame="none" !ls -la @@ -57,21 +57,21 @@ How is auth handled in @packages/functions/src/api/index.ts? ## 명령 -opencode TUI를 사용할 때, `/`를 입력하여 명령 이름을 따라 작업을 신속하게 실행할 수 있습니다. 예를 들면: +OpenCode TUI를 사용할 때 `/` 뒤에 명령 이름을 입력하여 작업을 빠르게 실행할 수 있습니다. 예를 들어: ```bash frame="none" /help ``` -대부분의 명령은 `ctrl+x`를 `ctrl+x`가 기본 리더 키입니다. [더 알아보기](/docs/keybinds). +대부분의 명령에는 기본 리더 키인 `ctrl+x`를 사용하는 키바인드도 있습니다. [더 알아보기](/docs/keybinds). -여기에 모든 가능한 슬래시 명령이 있습니다. +사용 가능한 모든 슬래시 명령은 다음과 같습니다: --- -### /connect +### connect -opencode에 대한 공급자를 추가합니다. 사용 가능한 공급자에서 선택하고 API 키를 추가 할 수 있습니다. +OpenCode에 공급자를 추가합니다. 사용 가능한 공급자 중에서 선택하고 API 키를 추가할 수 있습니다. ```bash frame="none" /connect @@ -79,67 +79,67 @@ opencode에 대한 공급자를 추가합니다. 사용 가능한 공급자에 --- -### /compact +### compact -현재 세션을 압축합니다. 앨리스 : `/summarize` +현재 세션을 압축합니다. _별칭_: `/summarize` ```bash frame="none" /compact ``` -** Keybind:** `ctrl+x c` +**키바인드:** `ctrl+x c` --- -### /details +### details -토글 툴 실행 세부 사항. +도구 실행 세부 정보 토글. ```bash frame="none" /details ``` -** Keybind:** `ctrl+x d` +**키바인드:** `ctrl+x d` --- -### /editor +### editor -메시지를 작성하기 위한 외부 편집기를 엽니다. `EDITOR` 환경에서 설정된 편집기를 사용합니다. [더 알아보기](#editor-setup). +메시지 작성을 위한 외부 편집기를 엽니다. `EDITOR` 환경 변수에 설정된 편집기를 사용합니다. [더 알아보기](#editor-setup). ```bash frame="none" /editor ``` -** Keybind:** `ctrl+x e` +**키바인드:** `ctrl+x e` --- -### /exit +### exit -opencode를 종료합니다. Aliases : `/quit`, `/q` +OpenCode를 종료합니다. _별칭_: `/quit`, `/q` ```bash frame="none" /exit ``` -** Keybind:** `ctrl+x q` +**키바인드:** `ctrl+x q` --- -### /export +### export -Markdown에 대한 현재 대화를 내보내고 기본 편집기에서 열립니다. `EDITOR` 환경에서 설정된 편집기를 사용합니다. [더 알아보기](#editor-setup). +현재 대화를 Markdown으로 내보내고 기본 편집기에서 엽니다. `EDITOR` 환경 변수에 설정된 편집기를 사용합니다. [더 알아보기](#editor-setup). ```bash frame="none" /export ``` -** Keybind:** `ctrl+x x` +**키바인드:** `ctrl+x x` --- -### /help +### help 도움말 대화 상자를 표시합니다. @@ -147,107 +147,106 @@ Markdown에 대한 현재 대화를 내보내고 기본 편집기에서 열립 /help ``` -** Keybind:** `ctrl+x h` +**키바인드:** `ctrl+x h` --- -###### /init +### init -`AGENTS.md` 파일을 만들거나 업데이트하십시오. [더 알아보기](/docs/rules). +`AGENTS.md` 파일을 생성하거나 업데이트합니다. [더 알아보기](/docs/rules). ```bash frame="none" /init ``` -** Keybind:** `ctrl+x i` +**키바인드:** `ctrl+x i` --- -## /models +### models -사용 가능한 모델 목록. +사용 가능한 모델 목록을 표시합니다. ```bash frame="none" /models ``` -** Keybind:** `ctrl+x m` +**키바인드:** `ctrl+x m` --- -## /new +### new -새로운 세션을 시작합니다. 앨리스 : `/clear` +새 세션을 시작합니다. _별칭_: `/clear` ```bash frame="none" /new ``` -** Keybind:** `ctrl+x n` +**키바인드:** `ctrl+x n` --- -##### /redo +### redo -이전 undone 메시지 Redo. `/undo`를 사용하는 후에만 유효한. +이전에 실행 취소한 메시지를 다시 실행합니다. `/undo`를 사용한 후에만 사용할 수 있습니다. :::tip -모든 파일 변경도 복원됩니다. +모든 파일 변경 사항도 복원됩니다. ::: -내부적으로 Git을 사용하여 파일 변경을 관리합니다. 그래서 프로젝트 ** -Git 저장소**입니다. +내부적으로 Git을 사용하여 파일 변경 사항을 관리합니다. 따라서 프로젝트가 **Git 저장소**여야 합니다. ```bash frame="none" /redo ``` -** Keybind:** `ctrl+x r` +**키바인드:** `ctrl+x r` --- -## /sessions +### sessions -세션 간 목록 및 전환. Aliases : `/resume`, `/continue` +세션 목록을 표시하고 세션 간을 전환합니다. _별칭_: `/resume`, `/continue` ```bash frame="none" /sessions ``` -** Keybind:** `ctrl+x l` +**키바인드:** `ctrl+x l` --- -## 공유 +### share -현재 세션 공유. [더 알아보기](/docs/share). +현재 세션을 공유합니다. [더 알아보기](/docs/share). ```bash frame="none" /share ``` -** Keybind:** `ctrl+x s` +**키바인드:** `ctrl+x s` --- -## /theme +### themes -사용할 수 있는 테마 목록. +사용 가능한 테마 목록을 표시합니다. ```bash frame="none" -/theme +/themes ``` -** Keybind:** `ctrl+x t` +**키바인드:** `ctrl+x t` --- -### /thinking +### thinking -대화의 사고/거주 블록의 가시성을 토합니다. 사용할 때, 확장 된 생각을 지원하는 모델의 이유 프로세스를 볼 수 있습니다. +대화에서 생각/추론 블록의 가시성을 토글합니다. 활성화하면 확장된 사고를 지원하는 모델의 추론 과정을 볼 수 있습니다. :::note -이 명령은 생각 블록이 ** 표시되었는지 여부 만 제어 ** - 모델의 소싱 기능을 활성화하거나 비활성화하지 않습니다. toggle 실제적인 reasoning 기능에, 모형 변종을 통해서 주기 위하여 `ctrl+t`를 이용합니다. +이 명령은 생각 블록이 **표시되는지 여부만 제어**하며 모델의 추론 기능을 활성화하거나 비활성화하지 않습니다. 실제 추론 기능을 토글하려면 `ctrl+t`를 사용하여 모델 변형을 순환하십시오. ::: ```bash frame="none" @@ -256,28 +255,27 @@ Git 저장소**입니다. --- -##### /undo +### undo -대화에서 마지막 메시지. 가장 최근의 사용자 메시지, 모든 후속 응답 및 모든 파일 변경 제거. +대화의 마지막 메시지를 실행 취소합니다. 가장 최근의 사용자 메시지, 모든 후속 응답 및 모든 파일 변경 사항을 제거합니다. :::tip -어떤 파일 변경도 복제됩니다. +모든 파일 변경 사항도 되돌려집니다. ::: -내부적으로 Git을 사용하여 파일 변경을 관리합니다. 그래서 프로젝트 ** -Git 저장소**입니다. +내부적으로 Git을 사용하여 파일 변경 사항을 관리합니다. 따라서 프로젝트가 **Git 저장소**여야 합니다. ```bash frame="none" /undo ``` -** Keybind:** `ctrl+x u` +**키바인드:** `ctrl+x u` --- -#### /unshare +### unshare -Unshare 현재 세션. [더 알아보기](/docs/share#un-sharing). +현재 세션 공유를 취소합니다. [더 알아보기](/docs/share#un-sharing). ```bash frame="none" /unshare @@ -285,9 +283,9 @@ Unshare 현재 세션. [더 알아보기](/docs/share#un-sharing). --- -## 편집기 설정 +## Editor setup -`/editor`와 `/export` 명령 모두는 `EDITOR` 환경변수에서 지정된 편집기를 사용합니다. +`/editor`와 `/export` 명령 모두 `EDITOR` 환경 변수에 지정된 편집기를 사용합니다. @@ -301,8 +299,7 @@ Unshare 현재 세션. [더 알아보기](/docs/share#un-sharing). export EDITOR="code --wait" ``` -영원한 만들기 위하여, 당신의 shell 프로파일에 이것을 추가하십시오; -`~/.bashrc`, `~/.zshrc`, 등. + 영구적으로 설정하려면 셸 프로필(`~/.bashrc`, `~/.zshrc` 등)에 추가하십시오. @@ -315,8 +312,7 @@ Unshare 현재 세션. [더 알아보기](/docs/share#un-sharing). set EDITOR=code --wait ``` -영구적으로, use **System Properties** > ** 환경 -변수**. + 영구적으로 설정하려면 **시스템 속성** > **환경 변수**를 사용하십시오. @@ -329,62 +325,72 @@ Unshare 현재 세션. [더 알아보기](/docs/share#un-sharing). $env:EDITOR = "code --wait" ``` -영구적으로 만들려면 PowerShell 프로파일에 추가하십시오. + 영구적으로 설정하려면 PowerShell 프로필에 추가하십시오. -인기있는 편집기 옵션은 다음과 같습니다 : +인기 있는 편집기 옵션은 다음과 같습니다: -- `code` - Visual Studio 코드 -- `cursor` - 커서 -- `windsurf` - 윈드 서핑 -- `nvim` - Neovim 편집기 -- `vim` - Vim 편집기 -- `nano` - 나노 편집기 -- `notepad` - 윈도우 노트패드 -- `subl` - 승화 텍스트 +- `code` - Visual Studio Code +- `cursor` - Cursor +- `windsurf` - Windsurf +- `nvim` - Neovim editor +- `vim` - Vim editor +- `nano` - Nano editor +- `notepad` - Windows Notepad +- `subl` - Sublime Text :::note -VS Code와 같은 일부 편집기는 `--wait` 플래그와 함께 시작해야합니다. +VS Code와 같은 일부 편집기는 `--wait` 플래그와 함께 시작해야 합니다. ::: -일부 편집기는 명령줄 인수가 차단 모드에서 실행되어야 합니다. `--wait` 플래그는 닫힐 때까지 편집기 프로세스 블록을 만듭니다. +일부 편집기는 차단 모드에서 실행하려면 명령줄 인수가 필요합니다. `--wait` 플래그는 편집기 프로세스가 닫힐 때까지 차단되도록 합니다. --- ## 구성 -opencode config 파일을 통해 TUI 동작을 사용자 정의할 수 있습니다. +`tui.json` (또는 `tui.jsonc`) 파일을 통해 TUI 동작을 사용자 정의할 수 있습니다. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +이는 서버/런타임 동작을 구성하는 `opencode.json`과는 별개입니다. + ### 옵션 -- `scroll_acceleration` - 부드러운 자연 스크롤을위한 macOS 스타일 스크롤 가속 가능. 사용할 때, 스크롤 속도는 빠른 스크롤 제스처로 증가하고 느린 움직임을 위해 정확한 유지. **이 설정은 `scroll_speed`를 통해 우선 순위를 부여하고 활성화 할 때. ** -- `scroll_speed` - 스크롤 명령 (최소 : `1`)을 사용하여 TUI 스크롤을 빠르게 제어합니다. 기본 `3`. ** 참고: `scroll_acceleration.enabled`가 `true`로 설정되면 무시됩니다.** +- `theme` - UI 테마를 설정합니다. [더 알아보기](/docs/themes). +- `keybinds` - 키보드 단축키를 사용자 정의합니다. [더 알아보기](/docs/keybinds). +- `scroll_acceleration.enabled` - 부드럽고 자연스러운 스크롤을 위해 macOS 스타일의 스크롤 가속을 활성화합니다. 활성화하면 빠른 스크롤 제스처로 스크롤 속도가 증가하고 느린 움직임에서는 정밀하게 유지됩니다. **이 설정은 `scroll_speed`보다 우선하며 활성화 시 이를 덮어씁니다.** +- `scroll_speed` - 스크롤 명령을 사용할 때 TUI 스크롤 속도를 제어합니다 (최소: `0.001`, 소수점 값 지원). 기본값은 `3`입니다. **참고: `scroll_acceleration.enabled`가 `true`로 설정되면 무시됩니다.** +- `diff_style` - diff 렌더링 방식을 제어합니다. `"auto"`는 터미널 너비에 적응하고, `"stacked"`는 항상 단일 열 레이아웃을 표시합니다. + +`OPENCODE_TUI_CONFIG`를 사용하여 사용자 정의 TUI 설정 경로를 로드할 수 있습니다. --- ## 사용자 정의 -명령 팔레트 (`ctrl+x h` 또는 `/help`)를 사용하여 TUI보기의 다양한 측면을 사용자 정의 할 수 있습니다. 재시작에 따른 설정 persist. +명령 팔레트(`ctrl+x h` 또는 `/help`)를 사용하여 TUI 보기의 다양한 측면을 사용자 정의할 수 있습니다. 설정은 다시 시작해도 유지됩니다. --- #### 사용자 이름 표시 -사용자 이름이 채팅 메시지에 나타나는지 여부를 수정합니다. 이것을 통해 접근: +채팅 메시지에 사용자 이름이 표시되는지 여부를 토글합니다. 다음을 통해 액세스: -- 명령 팔레트 : "username" 또는 "hide 사용자" 검색 -- 자동 설정은 TUI 세션을 통해 기억됩니다. +- 명령 팔레트: "username" 또는 "hide username" 검색 +- 설정은 자동으로 유지되며 TUI 세션 간에 기억됩니다. diff --git a/packages/web/src/content/docs/ko/zen.mdx b/packages/web/src/content/docs/ko/zen.mdx index 04d5c0df8e..ae598cee18 100644 --- a/packages/web/src/content/docs/ko/zen.mdx +++ b/packages/web/src/content/docs/ko/zen.mdx @@ -55,6 +55,7 @@ OpenCode Zen은 OpenCode의 다른 제공자와 동일한 방식으로 작동합 | 모델 | 모델 ID | 엔드포인트 | AI SDK 패키지 | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -64,28 +65,30 @@ OpenCode Zen은 OpenCode의 다른 제공자와 동일한 방식으로 작동합 | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Big Pickle | big-pickle | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -OpenCode 설정 파일에서 사용하는 [모델 ID](/docs/config/#models)는 `opencode/` 형식을 따릅니다. +OpenCode 설정 파일에서 사용하는 [모델 ID](/docs/config/#models)는 `opencode/` 형식을 따릅니다. 예를 들어 GPT 5.2 Codex의 경우 설정에서 `opencode/gpt-5.2-codex`와 같이 사용합니다. --- @@ -107,29 +110,34 @@ https://opencode.ai/zen/v1/models | 모델 | 입력 | 출력 | 캐시 읽기 | 캐시 쓰기 | | --------------------------------- | ------ | ------ | --------- | --------- | | Big Pickle | Free | Free | Free | - | -| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.5 Free | Free | Free | Free | - | +| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | - | | MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | -| GLM 4.7 Free | Free | Free | Free | - | +| GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 Free | Free | Free | Free | - | | Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - | +| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Claude Sonnet 4.6 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.6 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4.5 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | -| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - | @@ -148,8 +156,6 @@ https://opencode.ai/zen/v1/models 무료 모델: -- GLM 5 Free는 한정된 기간 동안 OpenCode에서 제공됩니다. 해당 기간 동안 팀은 사용자 피드백을 수집하고 모델을 개선할 예정입니다. -- Kimi K2.5 Free는 한정된 기간 동안 OpenCode에서 제공됩니다. 해당 기간 동안 팀은 사용자 피드백을 수집하고 모델을 개선할 예정입니다. - MiniMax M2.5 Free는 한정된 기간 동안 OpenCode에서 제공됩니다. 해당 기간 동안 팀은 사용자 피드백을 수집하고 모델을 개선할 예정입니다. - Big Pickle은 한정된 기간 동안 OpenCode에서 무료로 제공되는 스텔스 모델입니다. 해당 기간 동안 팀은 사용자 피드백을 수집하고 모델을 개선할 예정입니다. @@ -169,7 +175,7 @@ https://opencode.ai/zen/v1/models 워크스페이스 전체 및 각 팀 구성원별로 월간 사용 한도를 설정할 수 있습니다. -예를 들어 월간 사용 한도를 $20로 설정한 경우, Zen은 한 달 동안 $20을 초과하여 사용하지 않습니다. +예를 들어 월간 사용 한도를 $20로 설정한 경우, Zen은 한 달 동안 $20을 초과하여 사용하지 않습니다. 다만 자동 충전이 활성화되어 있는 경우, 잔액이 $5 미만으로 내려가면 자동으로 충전이 이루어질 수 있으므로 실제 청구 금액이 $20을 초과할 수 있습니다. --- @@ -179,8 +185,6 @@ https://opencode.ai/zen/v1/models 당사의 모든 모델은 미국에서 호스팅됩니다. 당사 제공자는 데이터 무보존(zero-retention) 정책을 따르며, 아래의 예외를 제외하고는 귀하의 데이터를 모델 학습에 사용하지 않습니다. - Big Pickle: 무료 제공 기간 동안 수집된 데이터는 모델 개선을 위해 사용될 수 있습니다. -- GLM 5 Free: 무료 제공 기간 동안 수집된 데이터는 모델 개선을 위해 사용될 수 있습니다. -- Kimi K2.5 Free: 무료 제공 기간 동안 수집된 데이터는 모델 개선을 위해 사용될 수 있습니다. - MiniMax M2.5 Free: 무료 제공 기간 동안 수집된 데이터는 모델 개선을 위해 사용될 수 있습니다. - OpenAI APIs: 요청 데이터는 [OpenAI의 데이터 정책](https://platform.openai.com/docs/guides/your-data)에 따라 30일간 보관됩니다. - Anthropic APIs: 요청 데이터는 [Anthropic의 데이터 정책](https://docs.anthropic.com/en/docs/claude-code/data-usage)에 따라 30일간 보관됩니다. diff --git a/packages/web/src/content/docs/nb/cli.mdx b/packages/web/src/content/docs/nb/cli.mdx index 2f1b3884ea..409fdb2378 100644 --- a/packages/web/src/content/docs/nb/cli.mdx +++ b/packages/web/src/content/docs/nb/cli.mdx @@ -558,6 +558,7 @@ OpenCode kan konfigureres ved hjelp av miljøvariabler. | `OPENCODE_AUTO_SHARE` | boolsk | Del økter automatisk | | `OPENCODE_GIT_BASH_PATH` | streng | Bane til Git Bash-kjørbar på Windows | | `OPENCODE_CONFIG` | streng | Bane til konfigurasjonsfil | +| `OPENCODE_TUI_CONFIG` | streng | Bane til TUI-konfigurasjonsfil | | `OPENCODE_CONFIG_DIR` | streng | Bane til konfigurasjonskatalog | | `OPENCODE_CONFIG_CONTENT` | streng | Innebygd json-konfigurasjonsinnhold | | `OPENCODE_DISABLE_AUTOUPDATE` | boolsk | Deaktiver automatiske oppdateringskontroller | diff --git a/packages/web/src/content/docs/nb/config.mdx b/packages/web/src/content/docs/nb/config.mdx index 8f54335794..e8b32d5a06 100644 --- a/packages/web/src/content/docs/nb/config.mdx +++ b/packages/web/src/content/docs/nb/config.mdx @@ -14,10 +14,11 @@ OpenCode støtter både **JSON** og **JSONC** (JSON med kommentarer) formater. ```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", - // Theme configuration - "theme": "opencode", "model": "anthropic/claude-sonnet-4-5", "autoupdate": true, + "server": { + "port": 4096, + }, } ``` @@ -301,12 +302,12 @@ Bærer-tokens (`AWS_BEARER_TOKEN_BEDROCK` eller `/connect`) har forrang over pro ### Temaer -Du kan konfigurere temaet du vil bruke i OpenCode-konfigurasjonen gjennom alternativet `theme`. +Angi UI-temaet ditt i `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "theme": "" + "$schema": "https://opencode.ai/tui.json", + "theme": "tokyonight" } ``` @@ -406,11 +407,11 @@ Du kan også definere kommandoer ved å bruke markdown-filer i `~/.config/openco ### Tastebindinger -Du kan tilpasse tastebindingene dine gjennom alternativet `keybinds`. +Tilpass tastebindinger i `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": {} } ``` @@ -490,13 +491,15 @@ Du kan styre kontekstkomprimering gjennom alternativet `compaction`. "$schema": "https://opencode.ai/config.json", "compaction": { "auto": true, - "prune": true + "prune": true, + "reserved": 10000 } } ``` - `auto` - Komprimer økten automatisk når konteksten er full (standard: `true`). - `prune` - Fjern gamle verktøyutdata for å spare tokens (standard: `true`). +- `reserved` - Token-buffer for komprimering. Etterlater nok vindu til å unngå overflyt under komprimering --- diff --git a/packages/web/src/content/docs/nb/custom-tools.mdx b/packages/web/src/content/docs/nb/custom-tools.mdx index 0b88f75077..505c261a0b 100644 --- a/packages/web/src/content/docs/nb/custom-tools.mdx +++ b/packages/web/src/content/docs/nb/custom-tools.mdx @@ -79,6 +79,32 @@ Dette lager to verktøy: `math_add` og `math_multiply`. --- +#### Navnekollisjoner med innebygde verktøy + +Egendefinerte verktøy er nøklet etter verktøynavn. Hvis et egendefinert verktøy bruker samme navn som et innebygd verktøy, vil det egendefinerte verktøyet ha forrang. + +For eksempel erstatter denne filen det innebygde `bash`-verktøyet: + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +Foretrekk unike navn med mindre du med vilje ønsker å erstatte et innebygd verktøy. Hvis du vil deaktivere et innebygd verktøy, men ikke overstyre det, bruk [tillatelser](/docs/permissions). +::: + +--- + ### Argumenter Du kan bruke `tool.schema`, som bare er [Zod](https://zod.dev), for å definere argumenttyper. diff --git a/packages/web/src/content/docs/nb/go.mdx b/packages/web/src/content/docs/nb/go.mdx new file mode 100644 index 0000000000..dcda3ec346 --- /dev/null +++ b/packages/web/src/content/docs/nb/go.mdx @@ -0,0 +1,159 @@ +--- +title: Go +description: Lavkostnadsabonnement for åpne kodemodeller. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go er et lavkostnadsabonnement til **$10/måned** som gir deg pålitelig tilgang til populære åpne kodemodeller. + +:::note +OpenCode Go er for tiden i beta. +::: + +Go fungerer som enhver annen leverandør i OpenCode. Du abonnerer på OpenCode Go og +får din API-nøkkel. Det er **helt valgfritt** og du trenger ikke bruke det for å +bruke OpenCode. + +Det er designet primært for internasjonale brukere, med modeller driftet i USA, EU og Singapore for stabil global tilgang. + +--- + +## Bakgrunn + +Åpne modeller har blitt veldig bra. De når nå ytelse nær +proprietære modeller for kodeoppgaver. Og fordi mange leverandører kan servere dem +konkurransedyktig, er de vanligvis mye billigere. + +Imidlertid kan det være vanskelig å få pålitelig tilgang med lav ventetid. Leverandører +varierer i kvalitet og tilgjengelighet. + +:::tip +Vi testet en utvalgt gruppe modeller og leverandører som fungerer bra med OpenCode. +::: + +For å fikse dette gjorde vi et par ting: + +1. Vi testet en utvalgt gruppe åpne modeller og snakket med teamene deres om hvordan man + best kjører dem. +2. Vi jobbet deretter med noen få leverandører for å sikre at disse ble servert + riktig. +3. Til slutt ytelsestestet vi kombinasjonen av modell/leverandør og kom opp + med en liste som vi føler oss trygge på å anbefale. + +OpenCode Go gir deg tilgang til disse modellene for **$10/måned**. + +--- + +## Hvordan det fungerer + +OpenCode Go fungerer som enhver annen leverandør i OpenCode. + +1. Du logger deg inn på **OpenCode Zen**, abonnerer på Go, og + kopierer API-nøkkelen din. +2. Du kjører kommandoen `/connect` i TUI-en, velger `OpenCode Go`, og limer inn + API-nøkkelen din. +3. Kjør `/models` i TUI-en for å se listen over modeller tilgjengelig gjennom Go. + +:::note +Bare ett medlem per arbeidsområde kan abonnere på OpenCode Go. +::: + +Den nåværende listen over modeller inkluderer: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +Listen over modeller kan endres etter hvert som vi tester og legger til nye. + +--- + +## Bruksgrenser + +OpenCode Go inkluderer følgende grenser: + +- **5 timers grense** — $12 i bruk +- **Ukentlig grense** — $30 i bruk +- **Månedlig grense** — $60 i bruk + +Grensene er definert i dollarverdi. Dette betyr at ditt faktiske antall forespørsler avhenger av modellen du bruker. Billigere modeller som MiniMax M2.5 tillater flere forespørsler, mens dyrere modeller som GLM-5 tillater færre. + +Tabellen nedenfor gir et estimert antall forespørsler basert på typiske Go-bruksmønstre: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ------------------------ | ----- | --------- | ------------ | +| forespørsler per 5 timer | 1,150 | 1,850 | 30,000 | +| forespørsler per uke | 2,880 | 4,630 | 75,000 | +| forespørsler per måned | 5,750 | 9,250 | 150,000 | + +Estimater er basert på observerte gjennomsnittlige forespørselsmønstre: + +- GLM-5 — 700 input, 52,000 cached, 150 output tokens per forespørsel +- Kimi K2.5 — 870 input, 55,000 cached, 200 output tokens per forespørsel +- MiniMax M2.5 — 300 input, 55,000 cached, 125 output tokens per forespørsel + +Du kan spore din nåværende bruk i **konsollen**. + +:::tip +Hvis du når bruksgrensen, kan du fortsette å bruke de gratis modellene. +::: + +Bruksgrenser kan endres etter hvert som vi lærer fra tidlig bruk og tilbakemeldinger. + +--- + +### Priser + +OpenCode Go er et **$10/måned** abonnementsplan. Nedenfor er prisene **per 1M tokens**. + +| Modell | Input | Output | Bufret lesing | +| ------------ | ----- | ------ | ------------- | +| GLM-5 | $1.00 | $3.20 | $0.20 | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | +| MiniMax M2.5 | $0.30 | $1.20 | $0.03 | + +--- + +### Bruk utover grensene + +Hvis du også har kreditter på din Zen-saldo, kan du aktivere alternativet **Bruk saldo** +i konsollen. Når aktivert, vil Go falle tilbake til Zen-saldoen din +etter at du har nådd bruksgrensene dine i stedet for å blokkere forespørsler. + +--- + +## Endepunkter + +Du kan også få tilgang til Go-modeller gjennom følgende API-endepunkter. + +| Modell | Modell-ID | Endepunkt | AI SDK Pakke | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +[Modell-ID-en](/docs/config/#models) i din OpenCode-konfigurasjon +bruker formatet `opencode-go/`. For eksempel, for Kimi K2.5, ville du +bruke `opencode-go/kimi-k2.5` i konfigurasjonen din. + +--- + +## Personvern + +Planen er designet primært for internasjonale brukere, med modeller driftet i USA, EU og Singapore for stabil global tilgang. + +Kontakt oss hvis du har noen spørsmål. + +--- + +## Mål + +Vi opprettet OpenCode Go for å: + +1. Gjøre AI-koding **tilgjengelig** for flere mennesker med et lavkostnadsabonnement. +2. Gi **pålitelig** tilgang til de beste åpne kodemodellene. +3. Kurere modeller som er **testet og ytelsestestet** for bruk av kodeagenter. +4. Ha **ingen innlåsing** ved å tillate deg å bruke hvilken som helst annen leverandør med OpenCode også. diff --git a/packages/web/src/content/docs/nb/keybinds.mdx b/packages/web/src/content/docs/nb/keybinds.mdx index d762a647f2..8314b4dd82 100644 --- a/packages/web/src/content/docs/nb/keybinds.mdx +++ b/packages/web/src/content/docs/nb/keybinds.mdx @@ -3,11 +3,11 @@ title: Tastebindinger description: Tilpass tastebindingene dine. --- -OpenCode har en liste over tastebindinger som du kan tilpasse gjennom OpenCode-konfigurasjonen. +OpenCode har en liste over tastebindinger som du kan tilpasse gjennom `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -117,11 +117,11 @@ Du trenger ikke å bruke en ledertast for tastebindingene dine, men vi anbefaler ## Deaktivering av tastebindinger -Du kan deaktivere en tastebinding ved å legge til tasten til konfigurasjonen med verdien "none". +Du kan deaktivere en tastebinding ved å legge til tasten til `tui.json` med en verdi på "none". -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/nb/lsp.mdx b/packages/web/src/content/docs/nb/lsp.mdx index c52b79a32d..924b0dad1a 100644 --- a/packages/web/src/content/docs/nb/lsp.mdx +++ b/packages/web/src/content/docs/nb/lsp.mdx @@ -27,6 +27,7 @@ OpenCode kommer med flere innebygde LSP-servere for populære språk: | gopls | .go | `go` kommando tilgjengelig | | hls | .hs, .lhs | `haskell-language-server-wrapper` kommando tilgjengelig | | jdtls | .java | `Java SDK (version 21+)` installert | +| julials | .jl | `julia` og `LanguageServer.jl` installert | | kotlin-ls | .kt, .kts | Installeres automatisk for Kotlin-prosjekter | | lua-ls | .lua | Installeres automatisk for Lua-prosjekter | | nixd | .nix | `nixd` kommando tilgjengelig | diff --git a/packages/web/src/content/docs/nb/modes.mdx b/packages/web/src/content/docs/nb/modes.mdx index 0322f06930..ccf9180e4e 100644 --- a/packages/web/src/content/docs/nb/modes.mdx +++ b/packages/web/src/content/docs/nb/modes.mdx @@ -4,7 +4,7 @@ description: Ulike moduser for forskjellige brukstilfeller. --- :::caution -Moduser er nå konfigurert gjennom alternativet `agent` i OpenCode-konfigurasjonen. De +Moduser konfigureres nå gjennom alternativet `agent` i OpenCode-konfigurasjonen. Alternativet `mode` er nå utdatert. [Finn ut mer](/docs/agents). ::: @@ -13,6 +13,14 @@ Moduser i OpenCode lar deg tilpasse oppførselen, verktøyene og prompter for ul Den kommer med to innebygde moduser: **bygg** og **plan**. Du kan tilpasse disse eller konfigurer din egen gjennom OpenCode-konfigurasjonen. +Du kan bytte mellom moduser under en økt eller konfigurere dem i konfigurasjonsfilen din. + +--- + +## Innebygd + +OpenCode kommer med to innebygde moduser. + --- ### Bygg @@ -34,6 +42,96 @@ Denne modusen er nyttig når du vil at AI skal analysere kode, foreslå endringe --- +## Bytte + +Du kan bytte mellom moduser under en økt ved å bruke _Tab_-tasten. Eller din konfigurerte `switch_mode` hurtigtast. + +Se også: [Formatters](/docs/formatters) for informasjon om kodeformateringskonfigurasjon. + +--- + +## Konfigurer + +Du kan tilpasse de innebygde modusene eller opprette din egen gjennom konfigurasjon. Moduser kan konfigureres på to måter: + +### JSON-konfigurasjon + +Konfigurer moduser i din `opencode.json` konfigurasjonsfil: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "mode": { + "build": { + "model": "anthropic/claude-sonnet-4-20250514", + "prompt": "{file:./prompts/build.txt}", + "tools": { + "write": true, + "edit": true, + "bash": true + } + }, + "plan": { + "model": "anthropic/claude-haiku-4-20250514", + "tools": { + "write": false, + "edit": false, + "bash": false + } + } + } +} +``` + +### Markdown-konfigurasjon + +Du kan også definere moduser ved hjelp av markdown-filer. Plasser dem i: + +- Globalt: `~/.config/opencode/modes/` +- Prosjekt: `.opencode/modes/` + +```markdown title="~/.config/opencode/modes/review.md" +--- +model: anthropic/claude-sonnet-4-20250514 +temperature: 0.1 +tools: + write: false + edit: false + bash: false +--- + +You are in code review mode. Focus on: + +- Code quality and best practices +- Potential bugs and edge cases +- Performance implications +- Security considerations + +Provide constructive feedback without making direct changes. +``` + +Filnavnet til markdown-filen blir modusnavnet (f.eks. `review.md` oppretter en `review`-modus). + +La oss se på disse konfigurasjonsalternativene i detalj. + +--- + +### Modell + +Bruk `model`-konfigurasjonen for å overstyre standardmodellen for denne modusen. Nyttig for å bruke forskjellige modeller optimalisert for forskjellige oppgaver. For eksempel en raskere modell for planlegging, en mer kapabel modell for implementering. + +```json title="opencode.json" +{ + "mode": { + "plan": { + "model": "anthropic/claude-haiku-4-20250514" + } + } +} +``` + +--- + ### Temperatur Kontroller tilfeldigheten og kreativiteten til AI-ens svar med `temperature`-konfigurasjonen. Lavere verdier gjør svarene mer fokuserte og deterministiske, mens høyere verdier øker kreativiteten og variasjonen. @@ -54,13 +152,171 @@ Kontroller tilfeldigheten og kreativiteten til AI-ens svar med `temperature`-kon Temperaturverdier varierer vanligvis fra 0,0 til 1,0: - **0.0-0.2**: Veldig fokuserte og deterministiske svar, ideelt for kodeanalyse og planlegging -- **0,3-0,5**: Balanserte svar med litt kreativitet, bra for generelle utviklingsoppgaver +- **0.3-0.5**: Balanserte svar med litt kreativitet, bra for generelle utviklingsoppgaver - **0.6-1.0**: Mer kreative og varierte svar, nyttig for idédugnad og utforskning +```json title="opencode.json" +{ + "mode": { + "analyze": { + "temperature": 0.1, + "prompt": "{file:./prompts/analysis.txt}" + }, + "build": { + "temperature": 0.3 + }, + "brainstorm": { + "temperature": 0.7, + "prompt": "{file:./prompts/creative.txt}" + } + } +} +``` + Hvis ingen temperatur er spesifisert, bruker OpenCode modellspesifikke standardinnstillinger (vanligvis 0 for de fleste modeller, 0,55 for Qwen-modeller). --- +### Prompt + +Angi en tilpasset systemprompt-fil for denne modusen med `prompt`-konfigurasjonen. Prompt-filen skal inneholde instruksjoner som er spesifikke for modusens formål. + +```json title="opencode.json" +{ + "mode": { + "review": { + "prompt": "{file:./prompts/code-review.txt}" + } + } +} +``` + +Denne banen er relativ til der konfigurasjonsfilen er plassert. Så dette fungerer for både den globale OpenCode-konfigurasjonen og den prosjektspesifikke konfigurasjonen. + +--- + +### Verktøy + +Kontroller hvilke verktøy som er tilgjengelige i denne modusen med `tools`-konfigurasjonen. Du kan aktivere eller deaktivere spesifikke verktøy ved å sette dem til `true` eller `false`. + +```json +{ + "mode": { + "readonly": { + "tools": { + "write": false, + "edit": false, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +Hvis ingen verktøy er spesifisert, er alle verktøy aktivert som standard. + +--- + +#### Tilgjengelige verktøy + +Her er alle verktøyene som kan kontrolleres gjennom moduskonfigurasjonen. + +| Verktøy | Beskrivelse | +| ----------- | --------------------------- | +| `bash` | Utfør shell-kommandoer | +| `edit` | Endre eksisterende filer | +| `write` | Opprett nye filer | +| `read` | Les filinnhold | +| `grep` | Søk i filinnhold | +| `glob` | Finn filer etter mønster | +| `list` | List opp kataloginnhold | +| `patch` | Bruk patcher på filer | +| `todowrite` | Administrer gjøremålslister | +| `todoread` | Les gjøremålslister | +| `webfetch` | Hent webinnhold | + +--- + +## Egendefinerte moduser + +Du kan opprette dine egne tilpassede moduser ved å legge dem til i konfigurasjonen. Her er eksempler på bruk av begge metodene: + +### Bruke JSON-konfigurasjon + +```json title="opencode.json" {4-14} +{ + "$schema": "https://opencode.ai/config.json", + "mode": { + "docs": { + "prompt": "{file:./prompts/documentation.txt}", + "tools": { + "write": true, + "edit": true, + "bash": false, + "read": true, + "grep": true, + "glob": true + } + } + } +} +``` + +### Bruke markdown-filer + +Opprett modusfiler i `.opencode/modes/` for prosjektspesifikke moduser eller `~/.config/opencode/modes/` for globale moduser: + +```markdown title=".opencode/modes/debug.md" +--- +temperature: 0.1 +tools: + bash: true + read: true + grep: true + write: false + edit: false +--- + +You are in debug mode. Your primary goal is to help investigate and diagnose issues. + +Focus on: + +- Understanding the problem through careful analysis +- Using bash commands to inspect system state +- Reading relevant files and logs +- Searching for patterns and anomalies +- Providing clear explanations of findings + +Do not make any changes to files. Only investigate and report. +``` + +```markdown title="~/.config/opencode/modes/refactor.md" +--- +model: anthropic/claude-sonnet-4-20250514 +temperature: 0.2 +tools: + edit: true + read: true + grep: true + glob: true +--- + +You are in refactoring mode. Focus on improving code quality without changing functionality. + +Priorities: + +- Improve code readability and maintainability +- Apply consistent naming conventions +- Reduce code duplication +- Optimize performance where appropriate +- Ensure all tests continue to pass +``` + +--- + ### Bruksområder Her er noen vanlige bruksområder for forskjellige moduser. diff --git a/packages/web/src/content/docs/nb/plugins.mdx b/packages/web/src/content/docs/nb/plugins.mdx index 6b6e1edf3f..27d23ec63a 100644 --- a/packages/web/src/content/docs/nb/plugins.mdx +++ b/packages/web/src/content/docs/nb/plugins.mdx @@ -1,6 +1,6 @@ --- title: Programtillegg -description: Skriv dine egne programtillegg for å utvide opencode. +description: Skriv dine egne programtillegg for å utvide OpenCode. --- Plugins lar deg utvide OpenCode ved å koble til ulike hendelser og tilpasse atferd. Du kan lage plugins for å legge til nye funksjoner, integrere med eksterne tjenester eller endre standardoppførselen til OpenCode. @@ -308,6 +308,10 @@ export const CustomToolsPlugin: Plugin = async (ctx) => { Dine egendefinerte verktøy vil være tilgjengelige for OpenCode sammen med innebygde verktøy. +:::note +Hvis et plugin-verktøy bruker samme navn som et innebygd verktøy, vil plugin-verktøyet ha forrang. +::: + --- ### Logging diff --git a/packages/web/src/content/docs/nb/providers.mdx b/packages/web/src/content/docs/nb/providers.mdx index 58d325cab8..682f923f8c 100644 --- a/packages/web/src/content/docs/nb/providers.mdx +++ b/packages/web/src/content/docs/nb/providers.mdx @@ -57,7 +57,7 @@ testet og verifisert for å fungere godt med OpenCode. [Finn ut mer](/docs/zen). Hvis du er ny, anbefaler vi å starte med OpenCode Zen. ::: -1. Kjør kommandoen `/connect` i TUI, velg opencode og gå til [opencode.ai/auth](https://opencode.ai/auth). +1. Kjør kommandoen `/connect` i TUI, velg `OpenCode Zen` og gå til [opencode.ai/auth](https://opencode.ai/zen). ```txt /connect @@ -84,6 +84,39 @@ Det fungerer som alle andre leverandører i OpenCode og er helt valgfritt å bru --- +## OpenCode Go + +OpenCode Go er en lavpris abonnementsplan som gir pålitelig tilgang til populære åpne kodemodeller levert av OpenCode-teamet som har vært +testet og verifisert for å fungere godt med OpenCode. + +1. Kjør kommandoen `/connect` i TUI, velg `OpenCode Go`, og gå til [opencode.ai/auth](https://opencode.ai/zen). + + ```txt + /connect + ``` + +2. Logg på, legg til faktureringsdetaljene dine og kopier API-nøkkelen. + +3. Lim inn API-nøkkelen. + + ```txt + ┌ API key + │ + │ + │ + └ enter + ``` + +4. Kjør `/models` i TUI for å se listen over modeller vi anbefaler. + + ```txt + /models + ``` + +Det fungerer som alle andre leverandører i OpenCode og er helt valgfritt å bruke. + +--- + ## Katalog La oss se på noen av leverandørene i detalj. Hvis du vil legge til en leverandør til diff --git a/packages/web/src/content/docs/nb/sdk.mdx b/packages/web/src/content/docs/nb/sdk.mdx index bbff8ebece..a947094476 100644 --- a/packages/web/src/content/docs/nb/sdk.mdx +++ b/packages/web/src/content/docs/nb/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## Strukturert Utdata + +Du kan be om strukturert JSON-utdata fra modellen ved å spesifisere et `format` med et JSON-skjema. Modellen vil bruke et `StructuredOutput`-verktøy for å returnere validert JSON som samsvarer med skjemaet ditt. + +### Grunnleggende bruk + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Access the structured output +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### Utdataformattyper + +| Type | Beskrivelse | +| ------------- | --------------------------------------------------------------- | +| `text` | Standard. Standard tekstrespons (ingen strukturert utdata) | +| `json_schema` | Returnerer validert JSON som samsvarer med det angitte skjemaet | + +### JSON Skjemaformat + +Når du bruker `type: 'json_schema'`, oppgi: + +| Felt | Type | Beskrivelse | +| ------------ | --------------- | ---------------------------------------------------------- | +| `type` | `'json_schema'` | Påkrevd. Spesifiserer JSON-skjemamodus | +| `schema` | `object` | Påkrevd. JSON Schema-objekt som definerer utdatastrukturen | +| `retryCount` | `number` | Valgfritt. Antall valideringsforsøk (standard: 2) | + +### Feilhåndtering + +Hvis modellen ikke klarer å produsere gyldig strukturert utdata etter alle forsøk, vil svaret inkludere en `StructuredOutputError`: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### Beste praksis + +1. **Gi klare beskrivelser** i skjemaegenskapene dine for å hjelpe modellen med å forstå hvilke data som skal trekkes ut +2. **Bruk `required`** for å spesifisere hvilke felt som må være til stede +3. **Hold skjemaer fokuserte** - komplekse nøstede skjemaer kan være vanskeligere for modellen å fylle ut riktig +4. **Angi passende `retryCount`** - øk for komplekse skjemaer, reduser for enkle + +--- + ## API-er SDK-en eksponerer alle server-API-er gjennom en typesikker klient. @@ -226,27 +298,27 @@ const { providers, default: defaults } = await client.config.providers() ### Sesjoner -| Metode | Beskrivelse | Merknader | -| ---------------------------------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -| `session.list()` | List økter | Returnerer Session[] | -| `session.get({ path })` | Hent økt | Returnerer Session | -| `session.children({ path })` | List barneøkter | Returnerer Session[] | -| `session.create({ body })` | Opprett økt | Returnerer Session | -| `session.delete({ path })` | Slett økt | Returnerer `boolean` | -| `session.update({ path, body })` | Oppdater øktegenskaper | Returnerer Session | -| `session.init({ path, body })` | Analyser appen og lag `AGENTS.md` | Returnerer `boolean` | -| `session.abort({ path })` | Avbryt en kjørende økt | Returnerer `boolean` | -| `session.share({ path })` | Del økten | Returnerer Session | -| `session.unshare({ path })` | Slutt å dele økten | Returnerer Session | -| `session.summarize({ path, body })` | Oppsummer økten | Returnerer `boolean` | -| `session.messages({ path })` | List meldinger i en økt | Returnerer `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ path })` | Hent meldingsdetaljer | Returnerer `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | Send melding | `body.noReply: true` returnerer UserMessage (kun kontekst). Standard returnerer AssistantMessage med AI svar | -| `session.command({ path, body })` | Send kommando til økt | Returnerer `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | Kjør en shell-kommando | Returnerer AssistantMessage | -| `session.revert({ path, body })` | Tilbakestill en melding | Returnerer Session | -| `session.unrevert({ path })` | Gjenopprett reverserte meldinger | Returnerer Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | Svar på en tillatelsesforespørsel | Returnerer `boolean` | +| Metode | Beskrivelse | Merknader | +| ---------------------------------------------------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | List økter | Returnerer Session[] | +| `session.get({ path })` | Hent økt | Returnerer Session | +| `session.children({ path })` | List barneøkter | Returnerer Session[] | +| `session.create({ body })` | Opprett økt | Returnerer Session | +| `session.delete({ path })` | Slett økt | Returnerer `boolean` | +| `session.update({ path, body })` | Oppdater øktegenskaper | Returnerer Session | +| `session.init({ path, body })` | Analyser appen og lag `AGENTS.md` | Returnerer `boolean` | +| `session.abort({ path })` | Avbryt en kjørende økt | Returnerer `boolean` | +| `session.share({ path })` | Del økten | Returnerer Session | +| `session.unshare({ path })` | Slutt å dele økten | Returnerer Session | +| `session.summarize({ path, body })` | Oppsummer økten | Returnerer `boolean` | +| `session.messages({ path })` | List meldinger i en økt | Returnerer `{ info: `Message`, parts: `Part[]`}[]` | +| `session.message({ path })` | Hent meldingsdetaljer | Returnerer `{ info: `Message`, parts: `Part[]`}` | +| `session.prompt({ path, body })` | Send melding | `body.noReply: true` returnerer UserMessage (kun kontekst). Standard returnerer AssistantMessage med AI svar. Støtter `body.outputFormat` for [strukturert utdata](#strukturert-utdata) | +| `session.command({ path, body })` | Send kommando til økt | Returnerer `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `session.shell({ path, body })` | Kjør en shell-kommando | Returnerer AssistantMessage | +| `session.revert({ path, body })` | Tilbakestill en melding | Returnerer Session | +| `session.unrevert({ path })` | Gjenopprett reverserte meldinger | Returnerer Session | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | Svar på en tillatelsesforespørsel | Returnerer `boolean` | --- diff --git a/packages/web/src/content/docs/nb/themes.mdx b/packages/web/src/content/docs/nb/themes.mdx index a294a6a0fa..2284848e31 100644 --- a/packages/web/src/content/docs/nb/themes.mdx +++ b/packages/web/src/content/docs/nb/themes.mdx @@ -3,9 +3,9 @@ title: Temaer description: Velg et innebygd tema eller definer ditt eget. --- -Med opencode kan du velge fra ett av flere innebygde temaer, bruke et tema som tilpasser seg terminaltemaet ditt, eller definere ditt eget tilpassede tema. +Med OpenCode kan du velge fra ett av flere innebygde temaer, bruke et tema som tilpasser seg terminaltemaet ditt, eller definere ditt eget tilpassede tema. -Som standard bruker opencode vårt eget `opencode`-tema. +Som standard bruker OpenCode vårt eget `opencode`-tema. --- @@ -23,7 +23,7 @@ Uten truecolor-støtte kan temaer vises med redusert fargenøyaktighet eller fal ## Innebygde temaer -opencode kommer med flere innebygde temaer. +OpenCode kommer med flere innebygde temaer. | Navn | Beskrivelse | | ---------------------- | ------------------------------------------------------------------------- | @@ -53,7 +53,7 @@ Og mer, vi legger stadig til nye temaer. Systemtemaet er for brukere som: -- Vil at opencode skal matche terminalens utseende +- Vil at OpenCode skal matche terminalens utseende - Bruker tilpassede terminalfargeskjemaer - Foretrekker et konsistent utseende på tvers av alle terminalapplikasjoner @@ -61,11 +61,11 @@ Systemtemaet er for brukere som: ## Bruke et tema -Du kan velge et tema ved å åpne temavelgeren med kommandoen `/theme`. Eller du kan spesifisere det i [config](/docs/config). +Du kan velge et tema ved å åpne temavelgeren med kommandoen `/theme`. Eller du kan spesifisere det i `tui.json`. -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` @@ -74,7 +74,7 @@ Du kan velge et tema ved å åpne temavelgeren med kommandoen `/theme`. Eller du ## Egendefinerte temaer -opencode støtter et fleksibelt JSON-basert temasystem som lar brukere enkelt lage og tilpasse temaer. +OpenCode støtter et fleksibelt JSON-basert temasystem som lar brukere enkelt lage og tilpasse temaer. --- diff --git a/packages/web/src/content/docs/nb/tui.mdx b/packages/web/src/content/docs/nb/tui.mdx index fae2a2364c..741ba46029 100644 --- a/packages/web/src/content/docs/nb/tui.mdx +++ b/packages/web/src/content/docs/nb/tui.mdx @@ -5,9 +5,9 @@ description: Bruke opencode-terminalbrukergrensesnittet. import { Tabs, TabItem } from "@astrojs/starlight/components" -opencode gir et interaktivt terminalgrensesnitt (TUI) for å jobbe med prosjektene dine med en LLM. +OpenCode gir et interaktivt terminalgrensesnitt (TUI) for å jobbe med prosjektene dine med en LLM. -Å kjøre opencode starter TUI for gjeldende katalog. +Å kjøre OpenCode starter TUI for gjeldende katalog. ```bash opencode @@ -57,7 +57,7 @@ Utdataene fra kommandoen legges til samtalen som et verktøyresultat. ## Kommandoer -Når du bruker opencode TUI, kan du skrive `/` etterfulgt av et kommandonavn for raskt å utføre handlinger. For eksempel: +Når du bruker OpenCode TUI, kan du skrive `/` etterfulgt av et kommandonavn for raskt å utføre handlinger. For eksempel: ```bash frame="none" /help @@ -71,7 +71,7 @@ Her er alle tilgjengelige slash-kommandoer: ### connect -Legg til en leverandør til opencode. Lar deg velge fra tilgjengelige leverandører og legge til deres API-nøkler. +Legg til en leverandør til OpenCode. Lar deg velge fra tilgjengelige leverandører og legge til deres API-nøkler. ```bash frame="none" /connect @@ -117,7 +117,7 @@ Veksle visning av verktøydetaljer. ### exit -Avslutt opencode. _Aliaser_: `/quit`, `/q` +Avslutt OpenCode. _Aliaser_: `/quit`, `/q` ```bash frame="none" /exit @@ -230,12 +230,12 @@ Del gjeldende økt. [Finn ut mer](/docs/share). --- -### theme +### themes Liste over tilgjengelige temaer. ```bash frame="none" -/theme +/themes ``` **Nøkkelbinding:** `ctrl+x t` @@ -355,24 +355,34 @@ Noen editorer trenger kommandolinjeargumenter for å kjøre i blokkeringsmodus. ## Konfigurasjon -Du kan tilpasse TUI-oppførselen gjennom opencode-konfigurasjonsfilen. +Du kan tilpasse TUI-oppførselen gjennom `tui.json` (eller `tui.jsonc`). -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +Dette er atskilt fra `opencode.json`, som konfigurerer server-/kjøretidsoppførsel. + ### Alternativer -- `scroll_acceleration` - Aktiver rulleakselerasjon i macOS-stil for jevn, naturlig rulling. Når aktivert, øker rullehastigheten med raske rullebevegelser og forblir presis for langsommere bevegelser. **Denne innstillingen har forrang over `scroll_speed` og overstyrer den når den er aktivert.** -- `scroll_speed` - Styrer hvor raskt TUI ruller når du bruker rullekommandoer (minimum: `1`). Standard er `3`. **Merk: Dette ignoreres hvis `scroll_acceleration.enabled` er satt til `true`.** +- `theme` - Angir UI-temaet ditt. [Finn ut mer](/docs/themes). +- `keybinds` - Tilpasser hurtigtaster. [Finn ut mer](/docs/keybinds). +- `scroll_acceleration.enabled` - Aktiver rulleakselerasjon i macOS-stil for jevn, naturlig rulling. Når aktivert, øker rullehastigheten med raske rullebevegelser og forblir presis for langsommere bevegelser. **Denne innstillingen har forrang over `scroll_speed` og overstyrer den når den er aktivert.** +- `scroll_speed` - Styrer hvor raskt TUI ruller når du bruker rullekommandoer (minimum: `0.001`, støtter desimalverdier). Standard er `3`. **Merk: Dette ignoreres hvis `scroll_acceleration.enabled` er satt til `true`.** +- `diff_style` - Kontrollerer diff-gjengivelse. `"auto"` tilpasser seg terminalbredden, `"stacked"` viser alltid en enkeltkolonneoppsett. + +Bruk `OPENCODE_TUI_CONFIG` for å laste en egendefinert TUI-konfigurasjonsbane. --- diff --git a/packages/web/src/content/docs/nb/zen.mdx b/packages/web/src/content/docs/nb/zen.mdx index f8dac0f391..51399615e5 100644 --- a/packages/web/src/content/docs/nb/zen.mdx +++ b/packages/web/src/content/docs/nb/zen.mdx @@ -14,7 +14,7 @@ OpenCode Zen er for øyeblikket i beta. ::: Zen fungerer som alle andre leverandører i OpenCode. Du logger på OpenCode Zen og får -din API nøkkel. Den er **helt valgfri** og du trenger ikke bruke den for å bruke den +din API nøkkel. Den er **helt valgfri** og du trenger ikke bruke den for å bruke OpenCode. --- @@ -64,6 +64,7 @@ Du kan også få tilgang til modellene våre gjennom følgende API-endepunkter. | Modell | Modell ID | Endepunkt | AI SDK Pakke | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -73,22 +74,24 @@ Du kan også få tilgang til modellene våre gjennom følgende API-endepunkter. | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -117,29 +120,34 @@ Vi støtter en pay-as-you-go-modell. Nedenfor er prisene **per 1 million tokens* | Modell | Inndata | Utdata | Bufret lesing | Bufret skriving | | --------------------------------- | ------- | ------ | ------------- | --------------- | | Big Pickle | Gratis | Gratis | Gratis | - | -| MiniMax M2.1 Free | Gratis | Gratis | Gratis | - | +| MiniMax M2.5 Free | Gratis | Gratis | Gratis | - | +| MiniMax M2.5 | $0,30 | $1,20 | $0,06 | - | | MiniMax M2.1 | $0,30 | $1,20 | $0,10 | - | -| GLM 4.7 Free | Gratis | Gratis | Gratis | - | +| GLM 5 | $1,00 | $3,20 | $0,20 | - | | GLM 4.7 | $0,60 | $2,20 | $0,10 | - | | GLM 4.6 | $0,60 | $2,20 | $0,10 | - | -| Kimi K2.5 Free | Gratis | Gratis | Gratis | - | | Kimi K2.5 | $0,60 | $3,00 | $0,08 | - | | Kimi K2 Thinking | $0,40 | $2,50 | - | - | | Kimi K2 | $0,40 | $2,50 | - | - | | Qwen3 Coder 480B | $0,45 | $1,50 | - | - | +| Claude Opus 4.6 (≤ 200K tokens) | $5,00 | $25,00 | $0,50 | $6,25 | +| Claude Opus 4.6 (> 200K tokens) | $10,00 | $37,50 | $1,00 | $12,50 | +| Claude Opus 4.5 | $5,00 | $25,00 | $0,50 | $6,25 | +| Claude Opus 4.1 | $15,00 | $75,00 | $1,50 | $18,75 | +| Claude Sonnet 4.6 (≤ 200K tokens) | $3,00 | $15,00 | $0,30 | $3,75 | +| Claude Sonnet 4.6 (> 200K tokens) | $6,00 | $22,50 | $0,60 | $7,50 | | Claude Sonnet 4.5 (≤ 200K tokens) | $3,00 | $15,00 | $0,30 | $3,75 | | Claude Sonnet 4.5 (> 200K tokens) | $6,00 | $22,50 | $0,60 | $7,50 | | Claude Sonnet 4 (≤ 200K tokens) | $3,00 | $15,00 | $0,30 | $3,75 | | Claude Sonnet 4 (> 200K tokens) | $6,00 | $22,50 | $0,60 | $7,50 | | Claude Haiku 4.5 | $1,00 | $5,00 | $0,10 | $1,25 | | Claude Haiku 3.5 | $0,80 | $4,00 | $0,08 | $1,00 | -| Claude Opus 4.6 (≤ 200K tokens) | $5,00 | $25,00 | $0,50 | $6,25 | -| Claude Opus 4.6 (> 200K tokens) | $10,00 | $37,50 | $1,00 | $12,50 | -| Claude Opus 4.5 | $5,00 | $25,00 | $0,50 | $6,25 | -| Claude Opus 4.1 | $15,00 | $75,00 | $1,50 | $18,75 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2,00 | $12,00 | $0,20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4,00 | $18,00 | $0,40 | - | | Gemini 3 Pro (≤ 200K tokens) | $2,00 | $12,00 | $0,20 | - | | Gemini 3 Pro (> 200K tokens) | $4,00 | $18,00 | $0,40 | - | | Gemini 3 Flash | $0,50 | $3,00 | $0,05 | - | +| GPT 5.3 Codex | $1,75 | $14,00 | $0,175 | - | | GPT 5.2 | $1,75 | $14,00 | $0,175 | - | | GPT 5.2 Codex | $1,75 | $14,00 | $0,175 | - | | GPT 5.1 | $1,07 | $8,50 | $0,107 | - | @@ -158,9 +166,7 @@ Kredittkortgebyrer overføres til kostpris (4,4 % + $0,30 per transaksjon); vi b De gratis modellene: -- GLM 4.7 Free er tilgjengelig på OpenCode i en begrenset periode. Teamet bruker denne tiden til å samle tilbakemeldinger og forbedre modellen. -- Kimi K2.5 Free er tilgjengelig på OpenCode i en begrenset periode. Teamet bruker denne tiden til å samle tilbakemeldinger og forbedre modellen. -- MiniMax M2.1 Free er tilgjengelig på OpenCode i en begrenset periode. Teamet bruker denne tiden til å samle tilbakemeldinger og forbedre modellen. +- MiniMax M2.5 Free er tilgjengelig på OpenCode i en begrenset periode. Teamet bruker denne tiden til å samle tilbakemeldinger og forbedre modellen. - Big Pickle er en stealth-modell som er gratis på OpenCode i en begrenset periode. Teamet bruker denne tiden til å samle tilbakemeldinger og forbedre modellen. Kontakt oss hvis du har spørsmål. @@ -191,9 +197,7 @@ belaster deg mer enn $20 hvis saldoen din går under $5. Alle våre modeller er hostet i USA. Leverandørene våre følger retningslinjer om ingen datalagring og bruker ikke dataene dine til modellopplæring, med følgende unntak: - Big Pickle: I løpet av gratisperioden kan innsamlede data brukes til å forbedre modellen. -- GLM 4.7 Free: I løpet av gratisperioden kan innsamlede data brukes til å forbedre modellen. -- Kimi K2.5 Free: I løpet av gratisperioden kan innsamlede data brukes til å forbedre modellen. -- MiniMax M2.1 Free: I løpet av gratisperioden kan innsamlede data brukes til å forbedre modellen. +- MiniMax M2.5 Free: I løpet av gratisperioden kan innsamlede data brukes til å forbedre modellen. - OpenAI APIer: Forespørsler oppbevares i 30 dager i samsvar med [OpenAIs datapolicyer](https://platform.openai.com/docs/guides/your-data). - Anthropic APIer: Forespørsler oppbevares i 30 dager i samsvar med [Anthropics datapolicyer](https://docs.anthropic.com/en/docs/claude-code/data-usage). @@ -251,4 +255,4 @@ Vi opprettet OpenCode Zen for å: 1. **Benchmark** de beste modellene/leverandørene for kodingsagenter. 2. Ha tilgang til alternativene for **høyeste kvalitet** og ikke nedgrader ytelsen eller rute trafikk til billigere leverandører. 3. Gi videre eventuelle **prisfall** ved å selge til kostpris; så det eneste påslaget er å dekke behandlingsgebyrene våre. -4. Ha **ingen låsing** ved å la deg bruke den med en hvilken som helst annen kodeagent. Og la deg alltid bruke en hvilken som helst annen leverandør med opencode også. +4. Ha **ingen låsing** ved å la deg bruke den med en hvilken som helst annen kodeagent. Og la deg alltid bruke en hvilken som helst annen leverandør med OpenCode også. diff --git a/packages/web/src/content/docs/pl/cli.mdx b/packages/web/src/content/docs/pl/cli.mdx index 3521859018..82ff7f52b2 100644 --- a/packages/web/src/content/docs/pl/cli.mdx +++ b/packages/web/src/content/docs/pl/cli.mdx @@ -558,6 +558,7 @@ OpenCode można skonfigurować za pomocą zmiennych środowiskowych. | `OPENCODE_AUTO_SHARE` | boolean | Automatycznie udostępniaj sesje | | `OPENCODE_GIT_BASH_PATH` | string | Ścieżka do pliku wykonywalnego Git Bash w systemie Windows | | `OPENCODE_CONFIG` | string | Ścieżka do pliku konfiguracyjnego | +| `OPENCODE_TUI_CONFIG` | string | Ścieżka do pliku konfiguracyjnego TUI | | `OPENCODE_CONFIG_DIR` | string | Ścieżka do katalogu konfiguracyjnego | | `OPENCODE_CONFIG_CONTENT` | string | Treść konfiguracji JSON (inline) | | `OPENCODE_DISABLE_AUTOUPDATE` | boolean | Wyłącz automatyczne sprawdzanie aktualizacji | diff --git a/packages/web/src/content/docs/pl/config.mdx b/packages/web/src/content/docs/pl/config.mdx index cde2e312ea..a6a6fb156d 100644 --- a/packages/web/src/content/docs/pl/config.mdx +++ b/packages/web/src/content/docs/pl/config.mdx @@ -94,7 +94,9 @@ Możesz włączyć serwer w konfiguracji projektu: ### Globalna -Umieść swoją globalną konfigurację OpenCode w `~/.config/opencode/opencode.json`. Użyj jej do ustawień ogólnych dla użytkownika, takich jak motywy, domyślny dostawca lub skróty klawiszowe. +Umieść swoją globalną konfigurację OpenCode w `~/.config/opencode/opencode.json`. Użyj jej do ustawień ogólnych dla użytkownika, takich jak dostawcy, modele i uprawnienia. + +Dla ustawień specyficznych dla TUI, użyj `~/.config/opencode/tui.json`. Konfiguracja globalna ma pierwszeństwo przed konfiguracją zdalną. @@ -104,8 +106,10 @@ Konfiguracja globalna ma pierwszeństwo przed konfiguracją zdalną. Dodaj `opencode.json` w katalogu głównym projektu. Konfiguracja projektu ma najwyższy priorytet wśród plików konfiguracyjnych — nadpisuje konfiguracje globalne i zdalne. +Dla ustawień TUI specyficznych dla projektu, dodaj plik `tui.json` obok niego. + :::tip -Dodaj ten plik do kontroli wersji, aby udostępniać konfigurację zespołowi. +Umieść konfigurację specyficzną dla projektu w katalogu głównym projektu. ::: Kiedy OpenCode się uruchamia, szuka pliku konfiguracyjnego w katalogu głównym repozytorium Git. @@ -150,28 +154,24 @@ Twój edytor powinien zapewniać walidację i autouzupełnianie na podstawie teg ### TUI -Możesz skonfigurować zachowanie TUI za pomocą opcji `tui`. +Użyj dedykowanego pliku `tui.json` (lub `tui.jsonc`) dla ustawień specyficznych dla TUI. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - }, - "diff_style": "auto" - } + "$schema": "https://opencode.ai/tui.json", + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` -Dostępne opcje: +Użyj `OPENCODE_TUI_CONFIG`, aby wskazać niestandardowy plik konfiguracyjny TUI. -- `scroll_acceleration.enabled` - Włącz przyspieszenie przewijania na gładzikach macOS. **Ma pierwszeństwo przed `scroll_speed`.** -- `scroll_speed` - Niestandardowy mnożnik szybkości przewijania (domyślnie: `3`, minimalnie: `1`). Ignorowane, jeśli `scroll_acceleration.enabled` ustawiono na `true`. -- `diff_style` – Sterowanie renderowaniem różnic. `"auto"` przełącza się w zależności od szerokości terminala, `"stacked"` zawsze wymusza pojedynczą kolumnę. +Przestarzałe klucze `theme`, `keybinds` i `tui` w `opencode.json` są wycofywane i automatycznie migrowane, gdy to możliwe. -[Dowiedz się więcej o korzystaniu z TUI](/docs/tui). +[Dowiedz się więcej o konfiguracji TUI tutaj](/docs/tui#configure). --- @@ -297,16 +297,16 @@ Token okaziciela (`AWS_BEARER_TOKEN_BEDROCK` lub `/connect`) ma pierwszeństwo p ### Theme (Motyw) -Skonfiguruj motyw interfejsu OpenCode za pomocą opcji `theme`. +Ustaw motyw interfejsu użytkownika w `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "theme": "" + "$schema": "https://opencode.ai/tui.json", + "theme": "tokyonight" } ``` -[Dowiedz się więcej o motywach](/docs/themes). +[Dowiedz się więcej tutaj](/docs/themes). --- @@ -402,16 +402,16 @@ Możesz także definiować polecenia przy użyciu plików Markdown w `~/.config/ ### Keybinds (Skróty klawiszowe) -Możesz dostosować skróty klawiszowe za pomocą opcji `keybinds`. +Dostosuj skróty klawiszowe w `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": {} } ``` -[Dowiedz się więcej o skrótach klawiszowych](/docs/keybinds). +[Dowiedz się więcej tutaj](/docs/keybinds). --- diff --git a/packages/web/src/content/docs/pl/custom-tools.mdx b/packages/web/src/content/docs/pl/custom-tools.mdx index eaf403d2de..7a38512c18 100644 --- a/packages/web/src/content/docs/pl/custom-tools.mdx +++ b/packages/web/src/content/docs/pl/custom-tools.mdx @@ -3,7 +3,7 @@ title: Narzędzia specjalistyczne description: Twórz narzędzi, które LLM mogą być uruchamiane w otwartym kodzie. --- -Narzędzia stosowane do funkcji, z których LLM może korzystać podczas rozmów. Współpracują z [wbudowanymi narzędziami] (./tools) opencode, wtyczka jak `read`, `write` i `bash`. +Narzędzia specjalistyczne to funkcje, które tworzysz i które LLM może wywoływać podczas rozmów. Współpracują one z [wbudowanymi narzędziami](/docs/tools) opencode, takimi jak `read`, `write` i `bash`. --- @@ -75,7 +75,33 @@ export const multiply = tool({ }) ``` -Tworzy do dwóch narzędzi: `math_add` i `math_multiply`. +Tworzy to dwa narzędzia: `math_add` i `math_multiply`. + +--- + +#### Kolizje nazw z wbudowanymi narzędziami + +Niestandardowe narzędzia są identyfikowane według nazwy narzędzia. Jeśli niestandardowe narzędzie używa tej samej nazwy co wbudowane narzędzie, niestandardowe narzędzie ma pierwszeństwo. + +Na przykład ten plik zastępuje wbudowane narzędzie `bash`: + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +Preferuj unikalne nazwy, chyba że celowo chcesz zastąpić wbudowane narzędzie. Jeśli chcesz wyłączyć wbudowane narzędzie, ale go nie nadpisywać, użyj [uprawnień](/docs/permissions). +::: --- @@ -135,9 +161,9 @@ export default tool({ ### Napisz narzędzie w Pythonie -Napisz swoje narzędzie w języku angielskim. Oto przykład dodania dwóch liczb przy użyciu języka Python. +Możesz pisać swoje narzędzia w dowolnym języku. Oto przykład dodania dwóch liczb przy użyciu języka Python. -Fragment utworu jako skrypt w języku Python: +Najpierw utwórz narzędzie jako skrypt w języku Python: ```python title=".opencode/tools/add.py" import sys @@ -147,7 +173,7 @@ b = int(sys.argv[2]) print(a + b) ``` -Utwór instrumentalny, który jest ukryty: +Następnie utwórz definicję narzędzia, która go wywołuje: ```ts title=".opencode/tools/python-add.ts" {10} import { tool } from "@opencode-ai/plugin" @@ -167,4 +193,4 @@ export default tool({ }) ``` -Tutaj istnieje narzędzie [`Bun.$`](https://bun.com/docs/runtime/shell) uruchamiające skryptu w języku Python. +Tutaj używamy narzędzia [`Bun.$`](https://bun.com/docs/runtime/shell) do uruchomienia skryptu w języku Python. diff --git a/packages/web/src/content/docs/pl/go.mdx b/packages/web/src/content/docs/pl/go.mdx new file mode 100644 index 0000000000..99547da18c --- /dev/null +++ b/packages/web/src/content/docs/pl/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: Tani abonament na otwarte modele kodowania. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go to tania subskrypcja za **10 USD miesięcznie**, która zapewnia niezawodny dostęp do popularnych otwartych modeli kodowania. + +:::note +OpenCode Go jest obecnie w fazie beta. +::: + +Go działa jak każdy inny dostawca w OpenCode. Subskrybujesz OpenCode Go i otrzymujesz swój klucz API. Jest to **całkowicie opcjonalne** i nie musisz z tego korzystać, aby używać OpenCode. + +Jest przeznaczony głównie dla użytkowników międzynarodowych, z modelami hostowanymi w USA, UE i Singapurze dla stabilnego dostępu globalnego. + +--- + +## Tło + +Otwarte modele stały się naprawdę dobre. Osiągają teraz wydajność zbliżoną do modeli komercyjnych w zadaniach związanych z kodowaniem. A ponieważ wielu dostawców może je obsługiwać konkurencyjnie, są zazwyczaj znacznie tańsze. + +Jednak uzyskanie niezawodnego dostępu o niskim opóźnieniu może być trudne. Dostawcy różnią się jakością i dostępnością. + +:::tip +Przetestowaliśmy wybraną grupę modeli i dostawców, którzy dobrze współpracują z OpenCode. +::: + +Aby to naprawić, zrobiliśmy kilka rzeczy: + +1. Przetestowaliśmy wybraną grupę otwartych modeli i rozmawialiśmy z ich zespołami o tym, jak najlepiej je uruchamiać. +2. Następnie współpracowaliśmy z kilkoma dostawcami, aby upewnić się, że są one obsługiwane poprawnie. +3. Na koniec przeprowadziliśmy testy porównawcze kombinacji modelu/dostawcy i stworzyliśmy listę, którą z czystym sumieniem polecamy. + +OpenCode Go daje dostęp do tych modeli za **10 USD miesięcznie**. + +--- + +## Jak to działa + +OpenCode Go działa jak każdy inny dostawca w OpenCode. + +1. Logujesz się do **OpenCode Zen**, subskrybujesz Go i kopiujesz swój klucz API. +2. Uruchamiasz polecenie `/connect` w TUI, wybierasz `OpenCode Go` i wklejasz swój klucz API. +3. Uruchom `/models` w TUI, aby zobaczyć listę modeli dostępnych przez Go. + +:::note +Tylko jeden członek na obszar roboczy może subskrybować OpenCode Go. +::: + +Obecna lista modeli obejmuje: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +Lista modeli może ulec zmianie w miarę testowania i dodawania nowych. + +--- + +## Limity użycia + +OpenCode Go obejmuje następujące limity: + +- **Limit 5-godzinny** — zużycie o wartości 12 USD +- **Limit tygodniowy** — zużycie o wartości 30 USD +- **Limit miesięczny** — zużycie o wartości 60 USD + +Limity są definiowane w wartości dolarowej. Oznacza to, że rzeczywista liczba żądań zależy od używanego modelu. Tańsze modele, takie jak MiniMax M2.5, pozwalają na więcej żądań, podczas gdy droższe modele, takie jak GLM-5, na mniej. + +Poniższa tabela przedstawia szacunkową liczbę żądań w oparciu o typowe wzorce użytkowania Go: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ------------------- | ----- | --------- | ------------ | +| żądania na 5 godzin | 1 150 | 1 850 | 30 000 | +| żądania na tydzień | 2 880 | 4 630 | 75 000 | +| żądania na miesiąc | 5 750 | 9 250 | 150 000 | + +Szacunki opierają się na zaobserwowanych średnich wzorcach żądań: + +- GLM-5 — 700 wejściowych, 52 000 zbuforowanych, 150 wyjściowych tokenów na żądanie +- Kimi K2.5 — 870 wejściowych, 55 000 zbuforowanych, 200 wyjściowych tokenów na żądanie +- MiniMax M2.5 — 300 wejściowych, 55 000 zbuforowanych, 125 wyjściowych tokenów na żądanie + +Możesz śledzić swoje bieżące zużycie w **konsoli**. + +:::tip +Jeśli osiągniesz limit użycia, możesz kontynuować korzystanie z darmowych modeli. +::: + +Limity użycia mogą ulec zmianie, gdy będziemy uczyć się na podstawie wczesnego użytkowania i opinii. + +--- + +### Cennik + +OpenCode Go to plan subskrypcji za **10 USD miesięcznie**. Poniżej znajdują się ceny **za 1 mln tokenów**. + +| Model | Wejście | Wyjście | Odczyt cache | +| ------------ | ------- | ------- | ------------ | +| GLM-5 | 1,00 $ | 3,20 $ | 0,20 $ | +| Kimi K2.5 | 0,60 $ | 3,00 $ | 0,10 $ | +| MiniMax M2.5 | 0,30 $ | 1,20 $ | 0,03 $ | + +--- + +### Użycie poza limitami + +Jeśli posiadasz również środki na swoim saldzie Zen, możesz włączyć opcję **Use balance** (Użyj salda) w konsoli. Po włączeniu, Go przełączy się na twoje saldo Zen po osiągnięciu limitów użycia, zamiast blokować żądania. + +--- + +## Punkty końcowe + +Możesz również uzyskać dostęp do modeli Go poprzez następujące punkty końcowe API. + +| Model | Identyfikator modelu | Endpoint | Pakiet AI SDK | +| ------------ | -------------------- | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +[Identyfikator modelu](/docs/config/#models) w twojej konfiguracji OpenCode używa formatu `opencode-go/`. Na przykład dla Kimi K2.5 użyłbyś `opencode-go/kimi-k2.5` w swojej konfiguracji. + +--- + +## Prywatność + +Plan jest przeznaczony głównie dla użytkowników międzynarodowych, z modelami hostowanymi w USA, UE i Singapurze dla stabilnego dostępu globalnego. + +Skontaktuj się z nami, jeśli masz jakiekolwiek pytania. + +--- + +## Cele + +Stworzyliśmy OpenCode Go, aby: + +1. Uczynić kodowanie z AI **dostępnym** dla większej liczby osób dzięki taniej subskrypcji. +2. Zapewnić **niezawodny** dostęp do najlepszych otwartych modeli kodowania. +3. Wyselekcjonować modele, które są **przetestowane i sprawdzone** pod kątem użycia z agentami kodującymi. +4. Nie wprowadzać **żadnych blokad (lock-in)**, pozwalając na korzystanie z dowolnego innego dostawcy w OpenCode. diff --git a/packages/web/src/content/docs/pl/keybinds.mdx b/packages/web/src/content/docs/pl/keybinds.mdx index f4995600da..03b9ec9c2a 100644 --- a/packages/web/src/content/docs/pl/keybinds.mdx +++ b/packages/web/src/content/docs/pl/keybinds.mdx @@ -3,11 +3,11 @@ title: Skróty klawiszowe description: Dostosuj swoje skróty klawiszowe. --- -opencode zawiera listę skrótów klawiszowych, które można zastosować poprzez opencode. +OpenCode zawiera listę skrótów klawiszowych, które można dostosować za pomocą `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -117,11 +117,11 @@ Nie musisz mieć klawisza wiodącego do skrótów klawiszowych, ale zalecamy to ## Wyłącz powiązanie klawiszy -Możesz podłączyć powiązanie klawiszy, dodając klucz do swojej konfiguracji z wartością „none”. +Możesz wyłączyć skrót klawiszowy, dodając klucz do `tui.json` z wartością "none". -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/pl/lsp.mdx b/packages/web/src/content/docs/pl/lsp.mdx index 8430bd9ca9..ec2edec430 100644 --- a/packages/web/src/content/docs/pl/lsp.mdx +++ b/packages/web/src/content/docs/pl/lsp.mdx @@ -27,6 +27,7 @@ OpenCode posiada kilka wbudowanych serwerów LSP dla następujących języków: | gopls | .go | Dostępne polecenie `go` | | hls | .hs, .lhs | Dostępne polecenie `haskell-language-server-wrapper` | | jdtls | .java | Zainstalowany `Java SDK (version 21+)` | +| julials | .jl | Zainstalowane `julia` i `LanguageServer.jl` | | kotlin-ls | .kt, .kts | Automatyczna instalacja dla Kotlin | | lua-ls | .lua | Automatyczna instalacja dla Lua | | nixd | .nix | Dostępne polecenie `nixd` | diff --git a/packages/web/src/content/docs/pl/plugins.mdx b/packages/web/src/content/docs/pl/plugins.mdx index e91900ad27..510c8a22e4 100644 --- a/packages/web/src/content/docs/pl/plugins.mdx +++ b/packages/web/src/content/docs/pl/plugins.mdx @@ -9,7 +9,7 @@ Aby znaleźć się z przykładami, przejrzyj [wtyczki](/docs/ecosystem#plugins) --- -## użyj wtyczki +## Użyj wtyczki Istnieją dwa sposoby ładowania wtyczek. @@ -51,7 +51,7 @@ Przeglądaj dostępną wtyczkę w [ekosystemie](/docs/ecosystem#plugins). --- -### Załaduj zamówienie +### Kolejność ładowania Wtyczki są ładowane ze wszystkich źródeł, a wszystkie hooki napisane po kolei. Kolejność ładowania do: @@ -310,7 +310,7 @@ Twoje narzędzie będzie dostępne dla otwartego kodu wraz z narzędziami użytk --- -### Wycięcie lasu +### Logowanie użyj `client.app.log()` zamiast `console.log` do rejestracji strukturalnego: diff --git a/packages/web/src/content/docs/pl/providers.mdx b/packages/web/src/content/docs/pl/providers.mdx index 58f824764e..fa50901103 100644 --- a/packages/web/src/content/docs/pl/providers.mdx +++ b/packages/web/src/content/docs/pl/providers.mdx @@ -57,7 +57,38 @@ przetestowane i zweryfikowane, aby dobrze współpracować z opencode. [Dowiedz Jeśli jesteś nowy, zalecamy rozpoczęcie od OpenCode Zen. ::: -1. Uruchom polecenie `/connect` w TUI, wybierz opencode i przejdź do [opencode.ai/auth](https://opencode.ai/auth). +1. Uruchom polecenie `/connect` w TUI, wybierz `OpenCode Zen` i przejdź do [opencode.ai/auth](https://opencode.ai/zen). + + ```txt + /connect + ``` + +2. Zaloguj się, dodaj szczegóły rozliczeniowe i skopiuj klucz API. + +3. Wklej swój klucz API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom `/models` w TUI, aby zobaczyć listę zalecanych przez nas modeli. + + ```txt + /models + ``` + +Działa jak każdy inny dostawca w opencode i jest całkowicie opcjonalny w użyciu. + +--- + +## OpenCode Go + +OpenCode Go to tani plan subskrypcji, który zapewnia niezawodny dostęp do popularnych modeli open coding dostarczanych przez zespół opencode, które zostały przetestowane i zweryfikowane pod kątem dobrej współpracy z opencode. + +1. Uruchom polecenie `/connect` w TUI, wybierz `OpenCode Go` i przejdź do [opencode.ai/auth](https://opencode.ai/zen). ```txt /connect @@ -470,7 +501,7 @@ Cloudflare AI Gateway umożliwia dostęp do modeli z OpenAI, Anthropic, Workers └ enter ``` - Or set it as an environment variable. + Lub ustaw go jako zmienną środowiskową. ```bash title="~/.bash_profile" export CLOUDFLARE_API_TOKEN=your-api-token @@ -834,11 +865,11 @@ Aby używać Google Vertex AI z opencode: 2. Ustaw wymagane zmienne środowiskowe: - `GOOGLE_CLOUD_PROJECT`: identyfikator Twojego projektu Google Cloud - `VERTEX_LOCATION` (opcjonalnie): region Vertex AI (domyślnie `global`) - - Authentication (choose one): + - Uwierzytelnianie (wybierz jedno): - `GOOGLE_APPLICATION_CREDENTIALS`: Ścieżka do pliku klucza JSON konta usługi - Uwierzytelnij się za pomocą interfejsu CLI gcloud: `gcloud auth application-default login` - Set them while running opencode. + Ustaw je podczas uruchamiania opencode. ```bash GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json GOOGLE_CLOUD_PROJECT=your-project-id opencode @@ -1479,6 +1510,39 @@ SAP AI Core zapewnia dostęp do ponad 40 modeli z OpenAI, Anthropic, Google, Ama --- +### STACKIT + +STACKIT AI Model Serving zapewnia w pełni zarządzane suwerenne środowisko hostingu dla modeli AI, koncentrując się na LLM, takich jak Llama, Mistral i Qwen, z maksymalną suwerennością danych na infrastrukturze europejskiej. + +1. Przejdź do [portalu STACKIT](https://portal.stackit.cloud), przejdź do **AI Model Serving**, i utwórz token autoryzacyjny dla swojego projektu. + + :::tip + Musisz posiadać konto klienta STACKIT, konto użytkownika i projekt przed utworzeniem tokenów autoryzacyjnych. + ::: + +2. Uruchom polecenie `/connect` i wyszukaj **STACKIT**. + + ```txt + /connect + ``` + +3. Wprowadź swój token autoryzacyjny STACKIT AI Model Serving. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Uruchom polecenie `/models`, aby wybrać jeden z dostępnych modeli, np. _Qwen3-VL 235B_ lub _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + ### OVHcloud AI Endpoints 1. Przejdź do [panelu OVHcloud](https://ovh.com/manager). Przejdź do sekcji `Public Cloud`, `AI & Machine Learning` > `AI Endpoints` i na karcie `API Keys` kliknij **Utwórz nowy klucz API**. diff --git a/packages/web/src/content/docs/pl/sdk.mdx b/packages/web/src/content/docs/pl/sdk.mdx index 3236e38c29..40099713ef 100644 --- a/packages/web/src/content/docs/pl/sdk.mdx +++ b/packages/web/src/content/docs/pl/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## Ustrukturyzowane Dane Wyjściowe + +Możesz zażądać ustrukturyzowanych danych wyjściowych JSON od modelu, określając `format` za pomocą schematu JSON. Model użyje narzędzia `StructuredOutput`, aby zwrócić zweryfikowany kod JSON pasujący do Twojego schematu. + +### Podstawowe użycie + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Access the structured output +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### Typy formatu wyjściowego + +| Typ | Opis | +| ------------- | ------------------------------------------------------------------------- | +| `text` | Domyślny. Standardowa odpowiedź tekstowa (brak ustrukturyzowanych danych) | +| `json_schema` | Zwraca zweryfikowany JSON pasujący do dostarczonego schematu | + +### Format JSON Schema + +Używając `type: 'json_schema'`, podaj: + +| Pole | Typ | Opis | +| ------------ | --------------- | ------------------------------------------------------------ | +| `type` | `'json_schema'` | Wymagane. Określa tryb schematu JSON | +| `schema` | `object` | Wymagane. Obiekt JSON Schema definiujący strukturę wyjściową | +| `retryCount` | `number` | Opcjonalne. Liczba ponownych prób walidacji (domyślnie: 2) | + +### Obsługa błędów + +Jeśli model nie wygeneruje prawidłowych ustrukturyzowanych danych wyjściowych po wszystkich próbach, odpowiedź będzie zawierać `StructuredOutputError`: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### Najlepsze praktyki + +1. **Podawaj jasne opisy** we właściwościach schematu, aby pomóc modelowi zrozumieć, jakie dane wyodrębnić +2. **Używaj `required`**, aby określić, które pola muszą być obecne +3. **Zachowaj schematy skoncentrowane** - złożone zagnieżdżone schematy mogą być trudniejsze dla modelu do poprawnego wypełnienia +4. **Ustaw odpowiedni `retryCount`** - zwiększ dla złożonych schematów, zmniejsz dla prostych + +--- + ## API Zestaw SDK udostępnia wszystkie interfejsy API serwera za pośrednictwem klienta bezpiecznego typu. diff --git a/packages/web/src/content/docs/pl/skills.mdx b/packages/web/src/content/docs/pl/skills.mdx index 9262d87e66..8dbb730120 100644 --- a/packages/web/src/content/docs/pl/skills.mdx +++ b/packages/web/src/content/docs/pl/skills.mdx @@ -141,8 +141,8 @@ Kontroluj, do których umiejętności agenci mogą uzyskać dostęp, używając | Permission | Behavior | | ---------- | ------------------------------------------------------ | -| `allow` | Skill loads immediately | -| `deny` | Skill hidden from agent, access rejected | +| `allow` | Umiejętność ładuje się natychmiast | +| `deny` | Umiejętność ukryta przed agentem, dostęp odrzucony | | `ask` | Użytkownik proszony o zatwierdzenie przed załadowaniem | Wzorce obsługują symbole wieloznaczne: `internal-*` odpowiada `internal-docs`, `internal-tools` itd. diff --git a/packages/web/src/content/docs/pl/themes.mdx b/packages/web/src/content/docs/pl/themes.mdx index d4272e2c9b..80a7808351 100644 --- a/packages/web/src/content/docs/pl/themes.mdx +++ b/packages/web/src/content/docs/pl/themes.mdx @@ -53,19 +53,19 @@ Motyw `system` został zaprojektowany tak, aby automatycznie dostosowywał się Motyw systemu przeznaczony jest dla użytkowników, którzy: -- Want opencode to match their terminal's appearance -- Użyj niestandardowych schematów kolorów terminali -- Prefer a consistent look across all terminal applications +- Chcą, aby OpenCode pasował do wyglądu ich terminala +- Używają niestandardowych schematów kolorów terminala +- Preferują spójny wygląd we wszystkich aplikacjach terminalowych --- ## Używanie motywu -Możesz wybrać motyw, wywołując opcję wyboru motywu za pomocą polecenia `/theme`. Możesz też określić to w [config](/docs/config). +Możesz wybrać motyw, wywołując opcję wyboru motywu za pomocą polecenia `/theme`. Możesz też określić to w `tui.json`. -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` diff --git a/packages/web/src/content/docs/pl/tui.mdx b/packages/web/src/content/docs/pl/tui.mdx index 6d693eb9e6..2d983cf84b 100644 --- a/packages/web/src/content/docs/pl/tui.mdx +++ b/packages/web/src/content/docs/pl/tui.mdx @@ -355,24 +355,34 @@ Niektórzy edytory potrzebują argumentów wiersza poleceń, aby działać w try ## Skonfiguruj -Możesz dostosować zachowanie TUI za pomocą pliku konfiguracyjnego opencode. +Możesz dostosować zachowanie TUI za pomocą pliku `tui.json` (lub `tui.jsonc`). -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +Jest to oddzielny plik od `opencode.json`, który konfiguruje zachowanie serwera/runtime. + ### Opcje -- `scroll_acceleration` — Włącz przyspieszenie przewijania w stylu macOS, aby zapewnić płynne, naturalne przewijanie. Po włączeniu prędkość przewijania wzrasta wraz z szybkimi gestami przewijania i pozostaje precyzyjna w przypadku wolniejszych ruchów. **To ustawienie ma pierwszeństwo przed `scroll_speed` i zastępuje je, gdy jest włączone.** -- `scroll_speed` - Kontroluje szybkość przewijania TUI podczas korzystania z poleceń przewijania (minimum: `1`). Wartość domyślna to `3`. **Uwaga: jest to ignorowane, jeśli `scroll_acceleration.enabled` jest ustawione na `true`.** +- `theme` - Ustawia motyw interfejsu. [Dowiedz się więcej](/docs/themes). +- `keybinds` - Dostosowuje skróty klawiszowe. [Dowiedz się więcej](/docs/keybinds). +- `scroll_acceleration.enabled` — Włącz przyspieszenie przewijania w stylu macOS, aby zapewnić płynne, naturalne przewijanie. Po włączeniu prędkość przewijania wzrasta wraz z szybkimi gestami przewijania i pozostaje precyzyjna w przypadku wolniejszych ruchów. **To ustawienie ma pierwszeństwo przed `scroll_speed` i zastępuje je, gdy jest włączone.** +- `scroll_speed` - Kontroluje szybkość przewijania TUI podczas korzystania z poleceń przewijania (minimum: `0.001`, obsługuje wartości dziesiętne). Wartość domyślna to `3`. **Uwaga: jest to ignorowane, jeśli `scroll_acceleration.enabled` jest ustawione na `true`.** +- `diff_style` - Steruje renderowaniem różnic. `"auto"` dostosowuje się do szerokości terminala, `"stacked"` zawsze pokazuje układ jednokolumnowy. + +Użyj `OPENCODE_TUI_CONFIG`, aby załadować niestandardową ścieżkę konfiguracji TUI. --- diff --git a/packages/web/src/content/docs/pl/zen.mdx b/packages/web/src/content/docs/pl/zen.mdx index 6d5d8c0bd7..dbb75489cb 100644 --- a/packages/web/src/content/docs/pl/zen.mdx +++ b/packages/web/src/content/docs/pl/zen.mdx @@ -62,8 +62,9 @@ Opłata jest pobierana za każde żądanie i możesz dodać kredyty do swojego k Dostęp do naszych modeli można również uzyskać za pośrednictwem następujących punktów końcowych API. -| Modelka | Identyfikator modelu | Punkt końcowy | Pakiet SDK AI | +| Model | Identyfikator modelu | Punkt końcowy | Pakiet SDK AI | | ------------------ | -------------------- | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -73,22 +74,24 @@ Dostęp do naszych modeli można również uzyskać za pośrednictwem następuj | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -114,32 +117,37 @@ https://opencode.ai/zen/v1/models Wspieramy model pay-as-you-go. Poniżej znajdują się ceny **za 1M tokenów**. -| Modelka | Wejście | Wyjście | Odczyt w pamięci podręcznej | Zapis w pamięci podręcznej | +| Model | Wejście | Wyjście | Odczyt w pamięci podręcznej | Zapis w pamięci podręcznej | | --------------------------------- | ------- | ------- | --------------------------- | -------------------------- | | Big Pickle | Free | Free | Free | - | -| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.5 Free | Free | Free | Free | - | +| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | - | | MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | -| GLM 4.7 Free | Free | Free | Free | - | +| GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 Free | Free | Free | Free | - | | Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - | +| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Claude Sonnet 4.6 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.6 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4.5 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | -| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - | @@ -158,10 +166,8 @@ Opłaty za karty kredytowe są przenoszone na koszt (4,4% + 0,30 USD za transakc Darmowe modele: -- GLM 4.7 Free jest dostępny na platformie opencode przez ograniczony czas. Zespół wykorzystuje ten czas na zbieranie opinii i ulepszanie modelu. -- Kimi K2.5 Free jest dostępny na opencode przez ograniczony czas. Zespół wykorzystuje ten czas na zbieranie opinii i ulepszanie modelu. -- MiniMax M2.1 Free jest dostępny na platformie opencode przez ograniczony czas. Zespół wykorzystuje ten czas na zbieranie opinii i ulepszanie modelu. -- Big Pickle to ukryty model, który jest bezpłatny w opencode przez ograniczony czas. Zespół wykorzystuje ten czas na zbieranie opinii i ulepszanie modelu. +- MiniMax M2.5 Free jest dostępny w OpenCode przez ograniczony czas. Zespół wykorzystuje ten czas na zbieranie opinii i ulepszanie modelu. +- Big Pickle to ukryty model, który jest bezpłatny w OpenCode przez ograniczony czas. Zespół wykorzystuje ten czas na zbieranie opinii i ulepszanie modelu. Skontaktuj się z nami, jeśli masz jakieś pytania. @@ -191,11 +197,9 @@ obciąży Cię kwotą wyższą niż 20 USD, jeśli saldo spadnie poniżej 5 USD. Wszystkie nasze modele są hostowane w USA. Nasi dostawcy przestrzegają polityki zerowego przechowywania i nie wykorzystują Twoich danych do szkolenia modeli, z następującymi wyjątkami: - Big Pickle: W okresie bezpłatnym zebrane dane mogą zostać wykorzystane do udoskonalenia modelu. -- GLM 4.7 Bezpłatna: W okresie bezpłatnym zebrane dane mogą zostać wykorzystane do udoskonalenia modelu. -- Kimi K2.5 Free: W okresie bezpłatnym zebrane dane mogą zostać wykorzystane do udoskonalenia modelu. -- MiniMax M2.1 Free: W okresie bezpłatnym zebrane dane mogą zostać wykorzystane do udoskonalenia modelu. +- MiniMax M2.5 Free: W okresie bezpłatnym zebrane dane mogą zostać wykorzystane do udoskonalenia modelu. - Interfejsy API OpenAI: żądania są przechowywane przez 30 dni zgodnie z [Zasadami dotyczącymi danych OpenAI](https://platform.openai.com/docs/guides/your-data). -- Interfejsy API Anthropic: żądania są przechowywane przez 30 dni zgodnie z [Zasadami dotyczącymi danych firmy Anthropic] (https://docs.anthropic.com/en/docs/claude-code/data-usage). +- Interfejsy API Anthropic: żądania są przechowywane przez 30 dni zgodnie z [Zasadami dotyczącymi danych firmy Anthropic](https://docs.anthropic.com/en/docs/claude-code/data-usage). --- diff --git a/packages/web/src/content/docs/pt-br/config.mdx b/packages/web/src/content/docs/pt-br/config.mdx index 405c537945..4684bb199e 100644 --- a/packages/web/src/content/docs/pt-br/config.mdx +++ b/packages/web/src/content/docs/pt-br/config.mdx @@ -14,10 +14,11 @@ O opencode suporta os formatos **JSON** e **JSONC** (JSON com Comentários). ```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", - // Theme configuration - "theme": "opencode", "model": "anthropic/claude-sonnet-4-5", "autoupdate": true, + "server": { + "port": 4096, + }, } ``` @@ -34,7 +35,7 @@ Os arquivos de configuração são **mesclados**, não substituídos. Os arquivos de configuração são mesclados, não substituídos. As configurações das seguintes localizações de configuração são combinadas. Configurações posteriores substituem as anteriores apenas para chaves conflitantes. Configurações não conflitantes de todas as configurações são preservadas. -Por exemplo, se sua configuração global define `theme: "opencode"` e `autoupdate: true`, e sua configuração de projeto define `model: "anthropic/claude-sonnet-4-5"`, a configuração final incluirá as três configurações. +Por exemplo, se sua configuração global define `autoupdate: true` e sua configuração de projeto define `model: "anthropic/claude-sonnet-4-5"`, a configuração final incluirá as duas configurações. --- @@ -95,7 +96,9 @@ Você pode habilitar servidores específicos em sua configuração local: ### Global -Coloque sua configuração global do opencode em `~/.config/opencode/opencode.json`. Use a configuração global para preferências de usuário, como temas, provedores ou atalhos de teclado. +Coloque sua configuração global do opencode em `~/.config/opencode/opencode.json`. Use a configuração global para preferências de todo o usuário, como provedores, modelos e permissões. + +Para configurações específicas do TUI, use `~/.config/opencode/tui.json`. A configuração global substitui os padrões organizacionais remotos. @@ -105,6 +108,8 @@ A configuração global substitui os padrões organizacionais remotos. Adicione `opencode.json` na raiz do seu projeto. A configuração do projeto tem a maior precedência entre os arquivos de configuração padrão - ela substitui tanto as configurações globais quanto as remotas. +Para configurações específicas do TUI do projeto, adicione `tui.json` junto a ele. + :::tip Coloque a configuração específica do projeto na raiz do seu projeto. ::: @@ -143,7 +148,9 @@ O diretório personalizado é carregado após a configuração global e os diret ## Esquema -O arquivo de configuração tem um esquema que está definido em [**`opencode.ai/config.json`**](https://opencode.ai/config.json). +O esquema de configuração do servidor/tempo de execução é definido em [**`opencode.ai/config.json`**](https://opencode.ai/config.json). + +A configuração do TUI usa [**`opencode.ai/tui.json`**](https://opencode.ai/tui.json). Seu editor deve ser capaz de validar e autocompletar com base no esquema. @@ -151,28 +158,24 @@ Seu editor deve ser capaz de validar e autocompletar com base no esquema. ### TUI -Você pode configurar as configurações específicas do TUI através da opção `tui`. +Use um arquivo `tui.json` (ou `tui.jsonc`) dedicado para configurações específicas do TUI. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - }, - "diff_style": "auto" - } + "$schema": "https://opencode.ai/tui.json", + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` -Opções disponíveis: +Use `OPENCODE_TUI_CONFIG` para apontar para um arquivo de configuração TUI personalizado. -- `scroll_acceleration.enabled` - Habilitar aceleração de rolagem estilo macOS. **Tem precedência sobre `scroll_speed`.** -- `scroll_speed` - Multiplicador de velocidade de rolagem personalizada (padrão: `3`, mínimo: `1`). Ignorado se `scroll_acceleration.enabled` for `true`. -- `diff_style` - Controlar a renderização de diffs. `"auto"` se adapta à largura do terminal, `"stacked"` sempre mostra uma coluna única. +Chaves legadas `theme`, `keybinds` e `tui` em `opencode.json` estão obsoletas e são migradas automaticamente quando possível. -[Saiba mais sobre o uso do TUI aqui](/docs/tui). +[Saiba mais sobre a configuração do TUI aqui](/docs/tui#configure). --- @@ -298,12 +301,12 @@ Tokens Bearer (`AWS_BEARER_TOKEN_BEDROCK` ou `/connect`) têm precedência sobre ### Temas -Você pode configurar o tema que deseja usar em sua configuração do opencode através da opção `theme`. +Defina seu tema de interface em `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "theme": "" + "$schema": "https://opencode.ai/tui.json", + "theme": "tokyonight" } ``` @@ -403,11 +406,11 @@ Você também pode definir comandos usando arquivos markdown em `~/.config/openc ### Atalhos de teclado -Você pode personalizar seus atalhos de teclado através da opção `keybinds`. +Personalize atalhos de teclado em `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": {} } ``` @@ -487,13 +490,15 @@ Você pode controlar o comportamento de compactação de contexto através da op "$schema": "https://opencode.ai/config.json", "compaction": { "auto": true, - "prune": true + "prune": true, + "reserved": 10000 } } ``` - `auto` - Compactar automaticamente a sessão quando o contexto estiver cheio (padrão: `true`). - `prune` - Remover saídas antigas de ferramentas para economizar tokens (padrão: `true`). +- `reserved` - Buffer de tokens para compactação. Deixa janela suficiente para evitar estouro durante a compactação --- @@ -673,6 +678,7 @@ Os caminhos dos arquivos podem ser: - Relativos ao diretório do arquivo de configuração - Ou caminhos absolutos começando com `/` ou `~` +- Esses são úteis para: diff --git a/packages/web/src/content/docs/pt-br/custom-tools.mdx b/packages/web/src/content/docs/pt-br/custom-tools.mdx index 43749200f8..515b8985a0 100644 --- a/packages/web/src/content/docs/pt-br/custom-tools.mdx +++ b/packages/web/src/content/docs/pt-br/custom-tools.mdx @@ -79,6 +79,32 @@ Isso cria duas ferramentas: `math_add` e `math_multiply`. --- +#### Colisões de nome com ferramentas integradas + +Ferramentas personalizadas são chaveadas pelo nome da ferramenta. Se uma ferramenta personalizada usar o mesmo nome que uma ferramenta integrada, a ferramenta personalizada tem precedência. + +Por exemplo, este arquivo substitui a ferramenta `bash` integrada: + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +Prefira nomes únicos, a menos que você queira intencionalmente substituir uma ferramenta integrada. Se você quiser desabilitar uma ferramenta integrada, mas não substituí-la, use [permissões](/docs/permissions). +::: + +--- + ### Argumentos Você pode usar `tool.schema`, que é apenas [Zod](https://zod.dev), para definir tipos de argumentos. @@ -126,7 +152,7 @@ export default tool({ }) ``` -Use `context.directory` para o diretório de trabalho da sessão. +Use `context.directory` para o diretório de trabalho da sessão. Use `context.worktree` para a raiz do worktree do git. --- diff --git a/packages/web/src/content/docs/pt-br/go.mdx b/packages/web/src/content/docs/pt-br/go.mdx new file mode 100644 index 0000000000..ee72ed49cb --- /dev/null +++ b/packages/web/src/content/docs/pt-br/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: Assinatura de baixo custo para modelos de codificação abertos. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +O OpenCode Go é uma assinatura de baixo custo de **$10/mês** que oferece acesso confiável a modelos de codificação abertos populares. + +:::note +O OpenCode Go está atualmente em beta. +::: + +O Go funciona como qualquer outro provedor no OpenCode. Você assina o OpenCode Go e obtém sua chave de API. É **totalmente opcional** e você não precisa usá-lo para usar o OpenCode. + +Ele é projetado principalmente para usuários internacionais, com modelos hospedados nos EUA, UE e Singapura para acesso global estável. + +--- + +## Contexto + +Modelos abertos ficaram realmente bons. Eles agora alcançam desempenho próximo aos modelos proprietários para tarefas de codificação. E como muitos provedores podem servi-los competitivamente, eles geralmente são muito mais baratos. + +No entanto, obter acesso confiável e de baixa latência a eles pode ser difícil. Os provedores variam em qualidade e disponibilidade. + +:::tip +Testamos um grupo selecionado de modelos e provedores que funcionam bem com o OpenCode. +::: + +Para corrigir isso, fizemos algumas coisas: + +1. Testamos um grupo selecionado de modelos abertos e conversamos com suas equipes sobre a melhor forma de executá-los. +2. Trabalhamos com alguns provedores para garantir que eles estivessem sendo servidos corretamente. +3. Finalmente, fizemos benchmarks da combinação modelo/provedor e chegamos a uma lista que nos sentimos bem em recomendar. + +O OpenCode Go oferece acesso a esses modelos por **$10/mês**. + +--- + +## Como funciona + +O OpenCode Go funciona como qualquer outro provedor no OpenCode. + +1. Você faz login no **OpenCode Zen**, assina o Go e copia sua chave de API. +2. Você executa o comando `/connect` na TUI, seleciona `OpenCode Go` e cola sua chave de API. +3. Execute `/models` na TUI para ver a lista de modelos disponíveis através do Go. + +:::note +Apenas um membro por workspace pode assinar o OpenCode Go. +::: + +A lista atual de modelos inclui: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +A lista de modelos pode mudar conforme testamos e adicionamos novos. + +--- + +## Limites de uso + +O OpenCode Go inclui os seguintes limites: + +- **Limite de 5 horas** — $12 de uso +- **Limite semanal** — $30 de uso +- **Limite mensal** — $60 de uso + +Os limites são definidos em valor monetário. Isso significa que sua contagem real de requisições depende do modelo que você usa. Modelos mais baratos como o MiniMax M2.5 permitem mais requisições, enquanto modelos de custo mais alto como o GLM-5 permitem menos. + +A tabela abaixo fornece uma estimativa de contagem de requisições baseada em padrões típicos de uso do Go: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ----------------------- | ----- | --------- | ------------ | +| requisições por 5 horas | 1.150 | 1.850 | 30.000 | +| requisições por semana | 2.880 | 4.630 | 75.000 | +| requisições por mês | 5.750 | 9.250 | 150.000 | + +As estimativas são baseadas em padrões médios de requisição observados: + +- GLM-5 — 700 tokens de entrada, 52.000 em cache, 150 tokens de saída por requisição +- Kimi K2.5 — 870 tokens de entrada, 55.000 em cache, 200 tokens de saída por requisição +- MiniMax M2.5 — 300 tokens de entrada, 55.000 em cache, 125 tokens de saída por requisição + +Você pode acompanhar seu uso atual no **console**. + +:::tip +Se você atingir o limite de uso, pode continuar usando os modelos gratuitos. +::: + +Os limites de uso podem mudar conforme aprendemos com o uso inicial e feedback. + +--- + +### Preços + +O OpenCode Go é um plano de assinatura de **$10/mês**. Abaixo estão os preços **por 1M de tokens**. + +| Modelo | Entrada | Saída | Leitura em Cache | +| ------------ | ------- | ----- | ---------------- | +| GLM-5 | $1.00 | $3.20 | $0.20 | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | +| MiniMax M2.5 | $0.30 | $1.20 | $0.03 | + +--- + +### Uso além dos limites + +Se você também tiver créditos em seu saldo Zen, pode ativar a opção **Use balance** (Usar saldo) no console. Quando ativada, o Go recorrerá ao seu saldo Zen depois que você atingir seus limites de uso, em vez de bloquear as requisições. + +--- + +## Endpoints + +Você também pode acessar os modelos Go através dos seguintes endpoints de API. + +| Modelo | ID do Modelo | Endpoint | Pacote AI SDK | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +O [model id](/docs/config/#models) (ID do modelo) na sua configuração do OpenCode usa o formato `opencode-go/`. Por exemplo, para o Kimi K2.5, você usaria `opencode-go/kimi-k2.5` na sua configuração. + +--- + +## Privacidade + +O plano é projetado principalmente para usuários internacionais, com modelos hospedados nos EUA, UE e Singapura para acesso global estável. + +Entre em contato conosco se tiver alguma dúvida. + +--- + +## Objetivos + +Criamos o OpenCode Go para: + +1. Tornar a IA de codificação **acessível** a mais pessoas com uma assinatura de baixo custo. +2. Fornecer acesso **confiável** aos melhores modelos de codificação abertos. +3. Curar modelos que são **testados e avaliados** para uso em agentes de codificação. +4. Não ter **nenhum bloqueio (lock-in)**, permitindo que você use qualquer outro provedor com o OpenCode também. diff --git a/packages/web/src/content/docs/pt-br/keybinds.mdx b/packages/web/src/content/docs/pt-br/keybinds.mdx index b4da4471aa..1829763ade 100644 --- a/packages/web/src/content/docs/pt-br/keybinds.mdx +++ b/packages/web/src/content/docs/pt-br/keybinds.mdx @@ -3,11 +3,11 @@ title: Atalhos de Teclado description: Personalize seus atalhos de teclado. --- -O opencode tem uma lista de atalhos de teclado que você pode personalizar através da configuração do opencode. +O opencode tem uma lista de atalhos de teclado que você pode personalizar através de `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -119,9 +119,9 @@ Você não precisa usar uma tecla líder para seus atalhos, mas recomendamos que Você pode desativar um atalho adicionando a tecla à sua configuração com um valor de "none". -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/pt-br/lsp.mdx b/packages/web/src/content/docs/pt-br/lsp.mdx index 6baf1813b3..cd8937b244 100644 --- a/packages/web/src/content/docs/pt-br/lsp.mdx +++ b/packages/web/src/content/docs/pt-br/lsp.mdx @@ -27,6 +27,7 @@ O opencode vem com vários servidores LSP integrados para linguagens populares: | gopls | .go | Comando `go` disponível | | hls | .hs, .lhs | Comando `haskell-language-server-wrapper` disponível | | jdtls | .java | `Java SDK (version 21+)` instalado | +| julials | .jl | `julia` e `LanguageServer.jl` instalados | | kotlin-ls | .kt, .kts | Instala automaticamente para projetos Kotlin | | lua-ls | .lua | Instala automaticamente para projetos Lua | | nixd | .nix | Comando `nixd` disponível | diff --git a/packages/web/src/content/docs/pt-br/plugins.mdx b/packages/web/src/content/docs/pt-br/plugins.mdx index bcf8f379bc..54c5b1ffac 100644 --- a/packages/web/src/content/docs/pt-br/plugins.mdx +++ b/packages/web/src/content/docs/pt-br/plugins.mdx @@ -307,6 +307,10 @@ O helper `tool` cria uma ferramenta personalizada que o opencode pode chamar. El Suas ferramentas personalizadas estarão disponíveis para o opencode junto com as ferramentas integradas. +:::note +Se uma ferramenta de plugin usar o mesmo nome que uma ferramenta integrada, a ferramenta de plugin tem precedência. +::: + --- ### Registro diff --git a/packages/web/src/content/docs/pt-br/providers.mdx b/packages/web/src/content/docs/pt-br/providers.mdx index 43f2e385f1..2ef2ebdc00 100644 --- a/packages/web/src/content/docs/pt-br/providers.mdx +++ b/packages/web/src/content/docs/pt-br/providers.mdx @@ -54,7 +54,39 @@ OpenCode Zen é uma lista de modelos fornecidos pela equipe do opencode que fora Se você é novo, recomendamos começar com o OpenCode Zen. ::: -1. Execute o comando `/connect` no TUI, selecione opencode e acesse [opencode.ai/auth](https://opencode.ai/auth). +1. Execute o comando `/connect` no TUI, selecione `OpenCode Zen` e acesse [opencode.ai/zen](https://opencode.ai/zen). + + ```txt + /connect + ``` + +2. Faça login, adicione seus dados de cobrança e copie sua chave da API. + +3. Cole sua chave da API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute `/models` no TUI para ver a lista de modelos que recomendamos. + + ```txt + /models + ``` + +Funciona como qualquer outro provedor no opencode e é completamente opcional. + +--- + +## OpenCode Go + +OpenCode Go é um plano de assinatura de baixo custo que fornece acesso confiável a modelos de codificação abertos populares fornecidos pela equipe do opencode que foram +testados e verificados para funcionar bem com o opencode. + +1. Execute o comando `/connect` no TUI, selecione `OpenCode Go` e acesse [opencode.ai/zen](https://opencode.ai/zen). ```txt /connect @@ -130,6 +162,8 @@ Para usar o Amazon Bedrock com o opencode: 2. **Configure a autenticação** usando um dos seguintes métodos: + *** + #### Variáveis de Ambiente (Início Rápido) Defina uma dessas variáveis de ambiente ao executar o opencode: @@ -152,6 +186,8 @@ Para usar o Amazon Bedrock com o opencode: export AWS_REGION=us-east-1 ``` + *** + #### Arquivo de Configuração (Recomendado) Para configuração específica do projeto ou persistente, use `opencode.json`: @@ -179,6 +215,8 @@ Para usar o Amazon Bedrock com o opencode: As opções do arquivo de configuração têm precedência sobre as variáveis de ambiente. ::: + *** + #### Avançado: Endpoints VPC Se você estiver usando endpoints VPC para Bedrock: @@ -202,12 +240,16 @@ Para usar o Amazon Bedrock com o opencode: A opção `endpoint` é um alias para a opção genérica `baseURL`, usando terminologia específica da AWS. Se tanto `endpoint` quanto `baseURL` forem especificados, `endpoint` tem precedência. ::: + *** + #### Métodos de Autenticação - **`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`**: Crie um usuário IAM e gere chaves de acesso no Console da AWS - **`AWS_PROFILE`**: Use perfis nomeados de `~/.aws/credentials`. Primeiro configure com `aws configure --profile my-profile` ou `aws sso login` - **`AWS_BEARER_TOKEN_BEDROCK`**: Gere chaves de API de longo prazo no console do Amazon Bedrock - **`AWS_WEB_IDENTITY_TOKEN_FILE` / `AWS_ROLE_ARN`**: Para EKS IRSA (IAM Roles for Service Accounts) ou outros ambientes Kubernetes com federação OIDC. Essas variáveis de ambiente são injetadas automaticamente pelo Kubernetes ao usar anotações de conta de serviço. + *** + #### Precedência de Autenticação O Amazon Bedrock usa a seguinte prioridade de autenticação: @@ -225,7 +267,8 @@ Para usar o Amazon Bedrock com o opencode: ``` :::note -Para perfis de inferência personalizados, use o nome do modelo e do provedor na chave e defina a propriedade `id` para o arn. Isso garante o cache correto: +Para perfis de inferência personalizados, use o nome do modelo e do provedor na chave e defina a propriedade `id` para o arn. Isso garante o cache correto. +::: ```json title="opencode.json" { @@ -243,8 +286,6 @@ Para perfis de inferência personalizados, use o nome do modelo e do provedor na } ``` -::: - --- ### Anthropic @@ -784,8 +825,6 @@ Para usar sua assinatura do GitHub Copilot com o opencode: :::note Alguns modelos podem precisar de uma [assinatura Pro+](https://github.com/features/copilot/plans) para usar. - -Alguns modelos precisam ser habilitados manualmente nas suas [configurações do GitHub Copilot](https://docs.github.com/en/copilot/how-tos/use-ai-models/configure-access-to-ai-models#setup-for-individual-use). ::: 1. Execute o comando `/connect` e procure por GitHub Copilot. @@ -803,7 +842,8 @@ Alguns modelos precisam ser habilitados manualmente nas suas [configurações do │ │ Digite o código: 8F43-6FCF │ - └ Aguardando autorização... + │ Aguardando autorização... + └ ``` 3. Agora execute o comando `/models` para selecionar o modelo que você deseja. @@ -1309,6 +1349,7 @@ Recomendamos se inscrever para [ChatGPT Plus ou Pro](https://chatgpt.com/pricing │ │ ChatGPT Plus/Pro │ Inserir manualmente a chave de API + │ └ ``` @@ -1472,6 +1513,39 @@ SAP AI Core fornece acesso a mais de 40 modelos do OpenAI, Anthropic, Google, Am --- +### STACKIT + +O STACKIT AI Model Serving fornece um ambiente de hospedagem soberano totalmente gerenciado para modelos de IA, com foco em LLMs como Llama, Mistral e Qwen, com máxima soberania de dados na infraestrutura europeia. + +1. Vá para o [Portal STACKIT](https://portal.stackit.cloud), navegue até **AI Model Serving** e crie um token de autenticação para o seu projeto. + + :::tip + Você precisa de uma conta de cliente STACKIT, conta de usuário e projeto antes de criar tokens de autenticação. + ::: + +2. Execute o comando `/connect` e procure por **STACKIT**. + + ```txt + /connect + ``` + +3. Insira seu token de autenticação do STACKIT AI Model Serving. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Execute o comando `/models` para selecionar entre os modelos disponíveis, como _Qwen3-VL 235B_ ou _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + ### OVHcloud AI Endpoints 1. Acesse o [painel OVHcloud](https://ovh.com/manager). Navegue até a seção `Public Cloud`, `AI & Machine Learning` > `AI Endpoints` e na aba `API Keys`, clique em **Criar uma nova chave da API**. @@ -1751,10 +1825,9 @@ Você pode usar qualquer provedor compatível com OpenAI com o opencode. A maior ┌ Adicionar credencial │ - ▲ Isso armazena apenas uma credencial para myprovider - você precisará configurá-lo no opencode.json, verifique a documentação para exemplos. - │ - ◇ Digite sua chave de API - │ sk-... + ◆ Select provider + │ ... + │ ● Other └ ``` @@ -1765,10 +1838,8 @@ Você pode usar qualquer provedor compatível com OpenAI com o opencode. A maior ┌ Adicionar credencial │ - ▲ Isso armazena apenas uma credencial para myprovider - você precisará configurá-lo no opencode.json, verifique a documentação para exemplos. - │ - ◇ Digite sua chave de API - │ sk-... + ◇ Enter provider id + │ myprovider └ ``` @@ -1808,8 +1879,6 @@ Você pode usar qualquer provedor compatível com OpenAI com o opencode. A maior } } } - } - } } } ``` @@ -1856,18 +1925,6 @@ Aqui está um exemplo definindo as opções `apiKey`, `headers` e `limit` do mod } } } - } - }, - "models": { - "my-model-name": { - "name": "Nome de Exibição do Meu Modelo", - "limit": { - "context": 200000, - "output": 65536 - } - } - } - } } } ``` diff --git a/packages/web/src/content/docs/pt-br/sdk.mdx b/packages/web/src/content/docs/pt-br/sdk.mdx index 672b852f6b..7fd765e4c1 100644 --- a/packages/web/src/content/docs/pt-br/sdk.mdx +++ b/packages/web/src/content/docs/pt-br/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## Saída Estruturada + +Você pode solicitar uma saída JSON estruturada do modelo especificando um `format` com um esquema JSON. O modelo usará uma ferramenta `StructuredOutput` para retornar um JSON validado correspondente ao seu esquema. + +### Uso Básico + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Acessar a saída estruturada +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### Tipos de Formato de Saída + +| Tipo | Descrição | +| ------------- | --------------------------------------------------------- | +| `text` | Padrão. Resposta de texto padrão (sem saída estruturada) | +| `json_schema` | Retorna JSON validado correspondente ao esquema fornecido | + +### Formato do Esquema JSON + +Ao usar `type: 'json_schema'`, forneça: + +| Campo | Tipo | Descrição | +| ------------ | --------------- | -------------------------------------------------------------- | +| `type` | `'json_schema'` | Obrigatório. Especifica o modo de esquema JSON | +| `schema` | `object` | Obrigatório. Objeto JSON Schema definindo a estrutura de saída | +| `retryCount` | `number` | Opcional. Número de tentativas de validação (padrão: 2) | + +### Tratamento de Erros + +Se o modelo falhar em produzir uma saída estruturada válida após todas as tentativas, a resposta incluirá um `StructuredOutputError`: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### Melhores Práticas + +1. **Forneça descrições claras** nas propriedades do seu esquema para ajudar o modelo a entender quais dados extrair +2. **Use `required`** para especificar quais campos devem estar presentes +3. **Mantenha os esquemas focados** - esquemas aninhados complexos podem ser mais difíceis para o modelo preencher corretamente +4. **Defina um `retryCount` apropriado** - aumente para esquemas complexos, diminua para os simples + +--- + ## APIs O SDK expõe todas as APIs do servidor através de um cliente seguro em tipos. @@ -226,27 +298,27 @@ const { providers, default: defaults } = await client.config.providers() ### Sessões -| Método | Descrição | Notas | -| ---------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | Listar sessões | Retorna Session[] | -| `session.get({ path })` | Obter sessão | Retorna Session | -| `session.children({ path })` | Listar sessões filhas | Retorna Session[] | -| `session.create({ body })` | Criar sessão | Retorna Session | -| `session.delete({ path })` | Deletar sessão | Retorna `boolean` | -| `session.update({ path, body })` | Atualizar propriedades da sessão | Retorna Session | -| `session.init({ path, body })` | Analisar app e criar `AGENTS.md` | Retorna `boolean` | -| `session.abort({ path })` | Abortar uma sessão em execução | Retorna `boolean` | -| `session.share({ path })` | Compartilhar sessão | Retorna Session | -| `session.unshare({ path })` | Descompartilhar sessão | Retorna Session | -| `session.summarize({ path, body })` | Resumir sessão | Retorna `boolean` | -| `session.messages({ path })` | Listar mensagens em uma sessão | Retorna `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ path })` | Obter detalhes da mensagem | Retorna `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | Enviar mensagem de prompt | `body.noReply: true` retorna UserMessage (apenas contexto). O padrão retorna AssistantMessage com resposta da AI | -| `session.command({ path, body })` | Enviar comando para a sessão | Retorna `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | Executar um comando shell | Retorna AssistantMessage | -| `session.revert({ path, body })` | Reverter uma mensagem | Retorna Session | -| `session.unrevert({ path })` | Restaurar mensagens revertidas | Retorna Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | Responder a um pedido de permissão | Retorna `boolean` | +| Método | Descrição | Notas | +| ---------------------------------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `session.list()` | Listar sessões | Retorna Session[] | +| `session.get({ path })` | Obter sessão | Retorna Session | +| `session.children({ path })` | Listar sessões filhas | Retorna Session[] | +| `session.create({ body })` | Criar sessão | Retorna Session | +| `session.delete({ path })` | Deletar sessão | Retorna `boolean` | +| `session.update({ path, body })` | Atualizar propriedades da sessão | Retorna Session | +| `session.init({ path, body })` | Analisar app e criar `AGENTS.md` | Retorna `boolean` | +| `session.abort({ path })` | Abortar uma sessão em execução | Retorna `boolean` | +| `session.share({ path })` | Compartilhar sessão | Retorna Session | +| `session.unshare({ path })` | Descompartilhar sessão | Retorna Session | +| `session.summarize({ path, body })` | Resumir sessão | Retorna `boolean` | +| `session.messages({ path })` | Listar mensagens em uma sessão | Retorna `{ info: `Message`, parts: `Part[]`}[]` | +| `session.message({ path })` | Obter detalhes da mensagem | Retorna `{ info: `Message`, parts: `Part[]`}` | +| `session.prompt({ path, body })` | Enviar mensagem de prompt | `body.noReply: true` retorna UserMessage (apenas contexto). O padrão retorna AssistantMessage com resposta da AI. Suporta `body.outputFormat` para [saída estruturada](#saída-estruturada) | +| `session.command({ path, body })` | Enviar comando para a sessão | Retorna `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `session.shell({ path, body })` | Executar um comando shell | Retorna AssistantMessage | +| `session.revert({ path, body })` | Reverter uma mensagem | Retorna Session | +| `session.unrevert({ path })` | Restaurar mensagens revertidas | Retorna Session | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | Responder a um pedido de permissão | Retorna `boolean` | --- diff --git a/packages/web/src/content/docs/pt-br/themes.mdx b/packages/web/src/content/docs/pt-br/themes.mdx index a1a5083cb8..5706d6e836 100644 --- a/packages/web/src/content/docs/pt-br/themes.mdx +++ b/packages/web/src/content/docs/pt-br/themes.mdx @@ -61,11 +61,11 @@ O tema do sistema é para usuários que: ## Usando um tema -Você pode selecionar um tema chamando a seleção de tema com o comando `/theme`. Ou você pode especificá-lo em sua [configuração](/docs/config). +Você pode selecionar um tema chamando a seleção de tema com o comando `/theme`. Ou você pode especificá-lo em `tui.json`. -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` diff --git a/packages/web/src/content/docs/pt-br/tui.mdx b/packages/web/src/content/docs/pt-br/tui.mdx index 17b9c7de0b..67de2138b6 100644 --- a/packages/web/src/content/docs/pt-br/tui.mdx +++ b/packages/web/src/content/docs/pt-br/tui.mdx @@ -234,7 +234,7 @@ Compartilhe a sessão atual. [Saiba mais](/docs/share). Liste os temas disponíveis. ```bash frame="none" -/theme +/themes ``` **Atalho:** `ctrl+x t` @@ -352,24 +352,34 @@ Alguns editores precisam de argumentos de linha de comando para rodar em modo bl ## Configuração -Você pode personalizar o comportamento do TUI através do seu arquivo de configuração do opencode. +Você pode personalizar o comportamento do TUI através de `tui.json` (ou `tui.jsonc`). -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +Isso é separado do `opencode.json`, que configura o comportamento do servidor/runtime. + ### Opções -- `scroll_acceleration` - Ative a aceleração de rolagem no estilo macOS para uma rolagem suave e natural. Quando ativado, a velocidade de rolagem aumenta com gestos de rolagem rápidos e permanece precisa para movimentos mais lentos. **Esta configuração tem precedência sobre `scroll_speed` e a substitui quando ativada.** -- `scroll_speed` - Controla quão rápido o TUI rola ao usar comandos de rolagem (mínimo: `1`). O padrão é `3`. **Nota: Isso é ignorado se `scroll_acceleration.enabled` estiver definido como `true`.** +- `theme` - Define o tema da sua interface. [Saiba mais](/docs/themes). +- `keybinds` - Personaliza atalhos de teclado. [Saiba mais](/docs/keybinds). +- `scroll_acceleration.enabled` - Ative a aceleração de rolagem no estilo macOS para uma rolagem suave e natural. Quando ativado, a velocidade de rolagem aumenta com gestos de rolagem rápidos e permanece precisa para movimentos mais lentos. **Esta configuração tem precedência sobre `scroll_speed` e a substitui quando ativada.** +- `scroll_speed` - Controla quão rápido o TUI rola ao usar comandos de rolagem (mínimo: `0.001`, suporta valores decimais). O padrão é `3`. **Nota: Isso é ignorado se `scroll_acceleration.enabled` estiver definido como `true`.** +- `diff_style` - Controla a renderização de diffs. `"auto"` se adapta à largura do terminal, `"stacked"` sempre mostra um layout de coluna única. + +Use `OPENCODE_TUI_CONFIG` para carregar um caminho de configuração TUI personalizado. --- diff --git a/packages/web/src/content/docs/pt-br/zen.mdx b/packages/web/src/content/docs/pt-br/zen.mdx index 203f0b3f9d..ba029fb7fc 100644 --- a/packages/web/src/content/docs/pt-br/zen.mdx +++ b/packages/web/src/content/docs/pt-br/zen.mdx @@ -1,19 +1,19 @@ --- title: Zen -description: Lista selecionada de modelos fornecidos pelo opencode. +description: Lista selecionada de modelos fornecidos pelo OpenCode. --- import config from "../../../../config.mjs" export const console = config.console export const email = `mailto:${config.email}` -O OpenCode Zen é uma lista de modelos testados e verificados fornecidos pela equipe do opencode. +O OpenCode Zen é uma lista de modelos testados e verificados fornecidos pela equipe do OpenCode. :::note O OpenCode Zen está atualmente em beta. ::: -O Zen funciona como qualquer outro provedor no opencode. Você faz login no OpenCode Zen e obtém sua chave de API. É **completamente opcional** e você não precisa usá-lo para utilizar o opencode. +O Zen funciona como qualquer outro provedor no OpenCode. Você faz login no OpenCode Zen e obtém sua chave de API. É **completamente opcional** e você não precisa usá-lo para utilizar o OpenCode. --- @@ -22,7 +22,7 @@ O Zen funciona como qualquer outro provedor no opencode. Você faz login no Open Existe um grande número de modelos disponíveis, mas apenas alguns desses modelos funcionam bem como agentes de codificação. Além disso, a maioria dos provedores é configurada de maneira muito diferente; portanto, você obtém desempenhos e qualidades muito diferentes. :::tip -Testamos um grupo selecionado de modelos e provedores que funcionam bem com o opencode. +Testamos um grupo selecionado de modelos e provedores que funcionam bem com o OpenCode. ::: Portanto, se você estiver usando um modelo através de algo como OpenRouter, você nunca pode ter certeza se está obtendo a melhor versão do modelo que deseja. @@ -39,7 +39,7 @@ O OpenCode Zen é um gateway de IA que lhe dá acesso a esses modelos. ## Como funciona -O OpenCode Zen funciona como qualquer outro provedor no opencode. +O OpenCode Zen funciona como qualquer outro provedor no OpenCode. 1. Você faz login no **OpenCode Zen**, adiciona seus dados de cobrança e copia sua chave de API. 2. Você executa o comando `/connect` no TUI, seleciona OpenCode Zen e cola sua chave de API. @@ -55,6 +55,7 @@ Você também pode acessar nossos modelos através dos seguintes endpoints da AP | Modelo | ID do Modelo | Endpoint | Pacote AI SDK | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -64,28 +65,30 @@ Você também pode acessar nossos modelos através dos seguintes endpoints da AP | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Big Pickle | big-pickle | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -O [id do modelo](/docs/config/#models) na sua configuração do opencode usa o formato `opencode/`. Por exemplo, para GPT 5.2 Codex, você usaria `opencode/gpt-5.2-codex` na sua configuração. +O [id do modelo](/docs/config/#models) na sua configuração do OpenCode usa o formato `opencode/`. Por exemplo, para GPT 5.2 Codex, você usaria `opencode/gpt-5.2-codex` na sua configuração. --- @@ -106,29 +109,34 @@ Nós suportamos um modelo de pagamento conforme o uso. Abaixo estão os preços | Modelo | Entrada | Saída | Leitura em Cache | Escrita em Cache | | --------------------------------- | ------- | ------ | ---------------- | ---------------- | | Big Pickle | Grátis | Grátis | Grátis | - | -| MiniMax M2.1 Free | Grátis | Grátis | Grátis | - | +| MiniMax M2.5 Free | Grátis | Grátis | Grátis | - | +| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | - | | MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | -| GLM 4.7 Free | Grátis | Grátis | Grátis | - | +| GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 Free | Grátis | Grátis | Grátis | - | | Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - | +| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Claude Sonnet 4.6 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.6 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4.5 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | -| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - | @@ -147,10 +155,8 @@ As taxas de cartão de crédito são repassadas ao custo (4,4% + $0,30 por trans Os modelos gratuitos: -- GLM 4.7 Free está disponível no opencode por tempo limitado. A equipe está usando esse tempo para coletar feedback e melhorar o modelo. -- Kimi K2.5 Free está disponível no opencode por tempo limitado. A equipe está usando esse tempo para coletar feedback e melhorar o modelo. -- MiniMax M2.1 Free está disponível no opencode por tempo limitado. A equipe está usando esse tempo para coletar feedback e melhorar o modelo. -- Big Pickle é um modelo oculto que está gratuito no opencode por tempo limitado. A equipe está usando esse tempo para coletar feedback e melhorar o modelo. +- MiniMax M2.5 Free está disponível no OpenCode por tempo limitado. A equipe está usando esse tempo para coletar feedback e melhorar o modelo. +- Big Pickle é um modelo oculto que está gratuito no OpenCode por tempo limitado. A equipe está usando esse tempo para coletar feedback e melhorar o modelo. Entre em contato conosco se você tiver alguma dúvida. @@ -177,9 +183,7 @@ Por exemplo, digamos que você defina um limite de uso mensal de $20, o Zen não Todos os nossos modelos estão hospedados nos EUA. Nossos provedores seguem uma política de zero retenção e não usam seus dados para treinamento de modelos, com as seguintes exceções: - Big Pickle: Durante seu período gratuito, os dados coletados podem ser usados para melhorar o modelo. -- GLM 4.7 Free: Durante seu período gratuito, os dados coletados podem ser usados para melhorar o modelo. -- Kimi K2.5 Free: Durante seu período gratuito, os dados coletados podem ser usados para melhorar o modelo. -- MiniMax M2.1 Free: Durante seu período gratuito, os dados coletados podem ser usados para melhorar o modelo. +- MiniMax M2.5 Free: Durante seu período gratuito, os dados coletados podem ser usados para melhorar o modelo. - APIs da OpenAI: As solicitações são retidas por 30 dias de acordo com as [Políticas de Dados da OpenAI](https://platform.openai.com/docs/guides/your-data). - APIs da Anthropic: As solicitações são retidas por 30 dias de acordo com as [Políticas de Dados da Anthropic](https://docs.anthropic.com/en/docs/claude-code/data-usage). @@ -233,4 +237,4 @@ Criamos o OpenCode Zen para: 1. **Benchmark** os melhores modelos/provedores para agentes de codificação. 2. Ter acesso às opções de **mais alta qualidade** e não degradar o desempenho ou redirecionar para provedores mais baratos. 3. Repassar quaisquer **reduções de preço** vendendo ao custo; assim, a única margem é para cobrir nossas taxas de processamento. -4. Não ter **vinculação** permitindo que você o use com qualquer outro agente de codificação. E sempre permitir que você use qualquer outro provedor com o opencode também. +4. Não ter **vinculação** permitindo que você o use com qualquer outro agente de codificação. E sempre permitir que você use qualquer outro provedor com o OpenCode também. diff --git a/packages/web/src/content/docs/ru/cli.mdx b/packages/web/src/content/docs/ru/cli.mdx index 1a1003a63a..5fa85a18fc 100644 --- a/packages/web/src/content/docs/ru/cli.mdx +++ b/packages/web/src/content/docs/ru/cli.mdx @@ -558,6 +558,7 @@ opencode можно настроить с помощью переменных с | `OPENCODE_AUTO_SHARE` | логическое значение | Автоматически делиться сеансами | | `OPENCODE_GIT_BASH_PATH` | строка | Путь к исполняемому файлу Git Bash в Windows | | `OPENCODE_CONFIG` | строка | Путь к файлу конфигурации | +| `OPENCODE_TUI_CONFIG` | строка | Путь к файлу конфигурации TUI | | `OPENCODE_CONFIG_DIR` | строка | Путь к каталогу конфигурации | | `OPENCODE_CONFIG_CONTENT` | строка | Встроенное содержимое конфигурации json | | `OPENCODE_DISABLE_AUTOUPDATE` | логическое значение | Отключить автоматическую проверку обновлений | diff --git a/packages/web/src/content/docs/ru/config.mdx b/packages/web/src/content/docs/ru/config.mdx index 14af31cfd7..5d91dc5e01 100644 --- a/packages/web/src/content/docs/ru/config.mdx +++ b/packages/web/src/content/docs/ru/config.mdx @@ -97,6 +97,8 @@ opencode поддерживает форматы **JSON** и **JSONC** (JSON с Поместите глобальную конфигурацию opencode в `~/.config/opencode/opencode.json`. Используйте глобальную конфигурацию для общепользовательских настроек, таких как темы, поставщики или привязки клавиш. +Для настроек, специфичных для TUI, используйте `~/.config/opencode/tui.json`. + Глобальная конфигурация переопределяет настройки по умолчанию для удаленной организации. --- @@ -105,6 +107,8 @@ opencode поддерживает форматы **JSON** и **JSONC** (JSON с Добавьте `opencode.json` в корень вашего проекта. Конфигурация проекта имеет наивысший приоритет среди стандартных файлов конфигурации — она переопределяет как глобальные, так и удаленные конфигурации. +Для настроек TUI, специфичных для проекта, добавьте `tui.json` рядом с ним. + :::tip Поместите конфигурацию конкретного проекта в корень вашего проекта. ::: @@ -145,34 +149,32 @@ opencode run "Hello world" Файл конфигурации имеет схему, определенную в [**`opencode.ai/config.json`**](https://opencode.ai/config.json). +Конфигурация TUI использует [**`opencode.ai/tui.json`**](https://opencode.ai/tui.json). + Ваш редактор должен иметь возможность проверять и автозаполнять данные на основе схемы. --- ### TUI -Вы можете настроить параметры TUI с помощью опции `tui`. +Используйте специальный файл `tui.json` (или `tui.jsonc`) для настроек, специфичных для TUI. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - }, - "diff_style": "auto" - } + "$schema": "https://opencode.ai/tui.json", + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` -Доступные варианты: +Используйте `OPENCODE_TUI_CONFIG`, чтобы указать на пользовательский файл конфигурации TUI. -- `scroll_acceleration.enabled` — включить ускорение прокрутки в стиле MacOS. **Имеет приоритет над `scroll_speed`.** -- `scroll_speed` — пользовательский множитель скорости прокрутки (по умолчанию: `3`, минимум: `1`). Игнорируется, если `scroll_acceleration.enabled` равен `true`. -- `diff_style` — управление рендерингом различий. `"auto"` адаптируется к ширине terminal, `"stacked"` всегда отображает один столбец. +Устаревшие ключи `theme`, `keybinds` и `tui` в `opencode.json` устарели и автоматически переносятся, когда это возможно. -[Подробнее об использовании TUI можно узнать здесь](/docs/tui). +[Подробнее об использовании TUI можно узнать здесь](/docs/tui#configure). --- @@ -298,12 +300,12 @@ Amazon Bedrock поддерживает конфигурацию, специфи ### theme -Вы можете настроить тему, которую хотите использовать, в конфигурации opencode с помощью опции `theme`. +Установите тему пользовательского интерфейса в `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "theme": "" + "$schema": "https://opencode.ai/tui.json", + "theme": "tokyonight" } ``` @@ -403,11 +405,11 @@ Amazon Bedrock поддерживает конфигурацию, специфи ### Сочетания клавиш -Вы можете настроить привязки клавиш с помощью опции `keybinds`. +Настройте привязки клавиш в `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": {} } ``` @@ -487,13 +489,15 @@ opencode автоматически загрузит все новые обно "$schema": "https://opencode.ai/config.json", "compaction": { "auto": true, - "prune": true + "prune": true, + "reserved": 10000 } } ``` - `auto` — автоматически сжимать сеанс при заполнении контекста (по умолчанию: `true`). - `prune` — удалить старые выходные данные инструмента для сохранения токенов (по умолчанию: `true`). +- `reserved` — Буфер токенов для сжатия. Оставляет достаточное окно, чтобы избежать переполнения во время сжатия. --- diff --git a/packages/web/src/content/docs/ru/go.mdx b/packages/web/src/content/docs/ru/go.mdx new file mode 100644 index 0000000000..17d1881f66 --- /dev/null +++ b/packages/web/src/content/docs/ru/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: Недорогая подписка на открытые модели для кодинга. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go — это недорогая подписка за **$10/месяц**, которая предоставляет надежный доступ к популярным открытым моделям для кодинга. + +:::note +OpenCode Go в настоящее время находится в бета-версии. +::: + +Go работает как любой другой провайдер в OpenCode. Вы подписываетесь на OpenCode Go и получаете свой API ключ. Это **полностью опционально**, и вам не нужно использовать его, чтобы пользоваться OpenCode. + +Он разработан в первую очередь для международных пользователей, с моделями, размещенными в США, ЕС и Сингапуре для стабильного глобального доступа. + +--- + +## Предыстория + +Открытые модели стали действительно хорошими. Теперь они достигают производительности, близкой к проприетарным моделям для задач кодинга. И поскольку многие провайдеры могут обслуживать их на конкурентной основе, они обычно намного дешевле. + +Однако получение надежного доступа к ним с низкой задержкой может быть сложным. Качество и доступность провайдеров варьируются. + +:::tip +Мы протестировали избранную группу моделей и провайдеров, которые хорошо работают с OpenCode. +::: + +Чтобы исправить это, мы сделали пару вещей: + +1. Мы протестировали избранную группу открытых моделей и поговорили с их командами о том, как лучше всего их запускать. +2. Затем мы работали с несколькими провайдерами, чтобы убедиться, что они обслуживаются правильно. +3. Наконец, мы провели бенчмаркинг комбинации модели/провайдера и составили список, который мы можем смело рекомендовать. + +OpenCode Go дает вам доступ к этим моделям за **$10/месяц**. + +--- + +## Как это работает + +OpenCode Go работает как любой другой провайдер в OpenCode. + +1. Вы входите в **OpenCode Zen**, подписываетесь на Go и копируете свой API ключ. +2. Вы запускаете команду `/connect` в TUI, выбираете `OpenCode Go` и вставляете свой API ключ. +3. Запустите `/models` в TUI, чтобы увидеть список моделей, доступных через Go. + +:::note +Только один участник рабочей области может подписаться на OpenCode Go. +::: + +Текущий список моделей включает: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +Список моделей может меняться по мере того, как мы тестируем и добавляем новые. + +--- + +## Лимиты использования + +OpenCode Go включает следующие лимиты: + +- **5-часовой лимит** — $12 использования +- **Недельный лимит** — $30 использования +- **Месячный лимит** — $60 использования + +Лимиты определены в денежном выражении. Это означает, что ваше фактическое количество запросов зависит от модели, которую вы используете. Более дешевые модели, такие как MiniMax M2.5, позволяют делать больше запросов, в то время как более дорогие модели, такие как GLM-5, позволяют меньше. + +Таблица ниже предоставляет примерное количество запросов на основе типичных паттернов использования Go: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ------------------- | ----- | --------- | ------------ | +| запросов за 5 часов | 1,150 | 1,850 | 30,000 | +| запросов в неделю | 2,880 | 4,630 | 75,000 | +| запросов в месяц | 5,750 | 9,250 | 150,000 | + +Оценки основаны на наблюдаемых средних паттернах запросов: + +- GLM-5 — 700 входных, 52,000 кэшированных, 150 выходных токенов на запрос +- Kimi K2.5 — 870 входных, 55,000 кэшированных, 200 выходных токенов на запрос +- MiniMax M2.5 — 300 входных, 55,000 кэшированных, 125 выходных токенов на запрос + +Вы можете отслеживать свое текущее использование в **консоли**. + +:::tip +Если вы достигнете лимита использования, вы можете продолжить использовать бесплатные модели. +::: + +Лимиты использования могут меняться по мере того, как мы учимся на раннем использовании и отзывах. + +--- + +### Ценообразование + +OpenCode Go — это план подписки за **$10/месяц**. Ниже приведены цены **за 1 млн токенов**. + +| Модель | Ввод | Вывод | Кэшированное чтение | +| ------------ | ----- | ----- | ------------------- | +| GLM-5 | $1.00 | $3.20 | $0.20 | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | +| MiniMax M2.5 | $0.30 | $1.20 | $0.03 | + +--- + +### Использование сверх лимитов + +Если у вас также есть кредиты на балансе Zen, вы можете включить опцию **Use balance** (Использовать баланс) в консоли. Когда она включена, Go переключится на ваш баланс Zen после того, как вы исчерпаете свои лимиты использования, вместо блокировки запросов. + +--- + +## Эндпоинты + +Вы также можете получить доступ к моделям Go через следующие API эндпоинты. + +| Модель | ID модели | Эндпоинт | Пакет AI SDK | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +[Model id](/docs/config/#models) в вашей конфигурации OpenCode использует формат `opencode-go/`. Например, для Kimi K2.5 вы бы использовали `opencode-go/kimi-k2.5` в вашей конфигурации. + +--- + +## Конфиденциальность + +План разработан в первую очередь для международных пользователей, с моделями, размещенными в США, ЕС и Сингапуре для стабильного глобального доступа. + +Свяжитесь с нами, если у вас есть вопросы. + +--- + +## Цели + +Мы создали OpenCode Go, чтобы: + +1. Сделать ИИ-кодинг **доступным** большему количеству людей с недорогой подпиской. +2. Обеспечить **надежный** доступ к лучшим открытым моделям для кодинга. +3. Отобрать модели, которые **протестированы и проверены** для использования агентами кодинга. +4. Не иметь **привязки к поставщику** (no lock-in), позволяя вам использовать любого другого провайдера с OpenCode. diff --git a/packages/web/src/content/docs/ru/keybinds.mdx b/packages/web/src/content/docs/ru/keybinds.mdx index 67d191ea2c..8a9a14ca1a 100644 --- a/packages/web/src/content/docs/ru/keybinds.mdx +++ b/packages/web/src/content/docs/ru/keybinds.mdx @@ -3,11 +3,11 @@ title: Сочетания клавиш description: Настройте свои сочетания клавиш. --- -opencode имеет список сочетаний клавиш, которые вы можете настроить через конфигурацию opencode. +opencode имеет список сочетаний клавиш, которые вы можете настроить через `tui.json`. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -117,11 +117,11 @@ opencode использует клавишу `leader` для большинст ## Отключение привязки клавиш -Вы можете отключить привязку клавиш, добавив ключ в свою конфигурацию со значением «none». +Вы можете отключить привязку клавиш, добавив ключ в `tui.json` со значением «none». -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/ru/providers.mdx b/packages/web/src/content/docs/ru/providers.mdx index 5984c89f43..c36dfd9f78 100644 --- a/packages/web/src/content/docs/ru/providers.mdx +++ b/packages/web/src/content/docs/ru/providers.mdx @@ -57,7 +57,39 @@ OpenCode Zen — это список моделей, предоставленн Если вы новичок, мы рекомендуем начать с OpenCode Zen. ::: -1. Запустите команду `/connect` в TUI, выберите opencode и перейдите по адресу [opencode.ai/auth](https://opencode.ai/auth). +1. Запустите команду `/connect` в TUI, выберите `OpenCode Zen` и перейдите по адресу [opencode.ai/auth](https://opencode.ai/zen). + + ```txt + /connect + ``` + +2. Войдите в систему, добавьте свои платежные данные и скопируйте ключ API. + +3. Вставьте свой ключ API. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите `/models` в TUI, чтобы просмотреть список рекомендуемых нами моделей. + + ```txt + /models + ``` + +Он работает как любой другой поставщик в opencode и его использование совершенно необязательно. + +--- + +## OpenCode Go + +OpenCode Go — это недорогой план подписки, обеспечивающий надежный доступ к популярным открытым моделям кодирования, предоставляемым командой opencode, которые были +протестированы и проверены на хорошую работу с opencode. + +1. Запустите команду `/connect` в TUI, выберите `OpenCode Go` и перейдите по адресу [opencode.ai/auth](https://opencode.ai/zen). ```txt /connect @@ -1479,6 +1511,39 @@ SAP AI Core предоставляет доступ к более чем 40 мо --- +### STACKIT + +STACKIT AI Model Serving предоставляет полностью управляемую суверенную среду хостинга для моделей ИИ, ориентированную на LLM, таких как Llama, Mistral и Qwen, с максимальным суверенитетом данных в европейской инфраструктуре. + +1. Перейдите на [портал STACKIT](https://portal.stackit.cloud), перейдите в **AI Model Serving** и создайте токен аутентификации для своего проекта. + + :::tip + Вам необходима учетная запись клиента STACKIT, учетная запись пользователя и проект перед созданием токенов аутентификации. + ::: + +2. Запустите команду `/connect` и найдите **STACKIT**. + + ```txt + /connect + ``` + +3. Введите свой токен аутентификации STACKIT AI Model Serving. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Запустите команду `/models`, чтобы выбрать одну из доступных моделей, например _Qwen3-VL 235B_ или _Llama 3.3 70B_. + + ```txt + /models + ``` + +--- + ### OVHcloud AI Endpoints 1. Перейдите к [OVHcloud Panel](https://ovh.com/manager). Перейдите в раздел `Public Cloud`, `AI & Machine Learning` > `AI Endpoints` и на вкладке `API Keys` нажмите **Создать новый ключ API**. diff --git a/packages/web/src/content/docs/ru/sdk.mdx b/packages/web/src/content/docs/ru/sdk.mdx index 1269d9fc08..0afdea1b6f 100644 --- a/packages/web/src/content/docs/ru/sdk.mdx +++ b/packages/web/src/content/docs/ru/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## Структурированный вывод + +Вы можете запросить структурированный вывод JSON от модели, указав `format` со схемой JSON. Модель будет использовать инструмент `StructuredOutput` для возврата проверенного JSON, соответствующего вашей схеме. + +### Основное использование + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Access the structured output +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### Типы форматов вывода + +| Тип | Описание | +| ------------- | ------------------------------------------------------------------------- | +| `text` | По умолчанию. Стандартный текстовый ответ (без структурированного вывода) | +| `json_schema` | Возвращает проверенный JSON, соответствующий предоставленной схеме | + +### Формат схемы JSON + +При использовании `type: 'json_schema'`, укажите: + +| Поле | Тип | Описание | +| ------------ | --------------- | ---------------------------------------------------------------------- | +| `type` | `'json_schema'` | Обязательно. Указывает режим схемы JSON | +| `schema` | `object` | Обязательно. Объект JSON Schema, определяющий структуру вывода | +| `retryCount` | `number` | Необязательно. Количество повторных попыток проверки (по умолчанию: 2) | + +### Обработка ошибок + +Если модель не может выдать действительный структурированный вывод после всех повторных попыток, ответ будет включать `StructuredOutputError`: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### Лучшие практики + +1. **Предоставляйте четкие описания** в свойствах вашей схемы, чтобы помочь модели понять, какие данные извлекать +2. **Используйте `required`**, чтобы указать, какие поля должны присутствовать +3. **Делайте схемы сфокусированными** — сложные вложенные схемы могут быть труднее для правильного заполнения моделью +4. **Устанавливайте соответствующий `retryCount`** — увеличивайте для сложных схем, уменьшайте для простых + +--- + ## API SDK предоставляет все серверные API через типобезопасный клиент. @@ -226,27 +298,27 @@ const { providers, default: defaults } = await client.config.providers() ### Сессии -| Метод | Описание | Примечания | -| ---------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | List sessions | Returns Session[] | -| `session.get({ path })` | Get session | Returns Session | -| `session.children({ path })` | List child sessions | Returns Session[] | -| `session.create({ body })` | Create session | Returns Session | -| `session.delete({ path })` | Delete session | Returns `boolean` | -| `session.update({ path, body })` | Update session properties | Returns Session | -| `session.init({ path, body })` | Analyze app and create `AGENTS.md` | Returns `boolean` | -| `session.abort({ path })` | Abort a running session | Returns `boolean` | -| `session.share({ path })` | Share session | Returns Session | -| `session.unshare({ path })` | Unshare session | Returns Session | -| `session.summarize({ path, body })` | Summarize session | Returns `boolean` | -| `session.messages({ path })` | List messages in a session | Returns `{ info: `Message`, parts: `Part[]`}[]` | -| `session.message({ path })` | Get message details | Returns `{ info: `Message`, parts: `Part[]`}` | -| `session.prompt({ path, body })` | Send prompt message | `body.noReply: true` returns UserMessage (context only). Default returns AssistantMessage with AI response | -| `session.command({ path, body })` | Send command to session | Returns `{ info: `AssistantMessage`, parts: `Part[]`}` | -| `session.shell({ path, body })` | Run a shell command | Returns AssistantMessage | -| `session.revert({ path, body })` | Revert a message | Returns Session | -| `session.unrevert({ path })` | Restore reverted messages | Returns Session | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | Respond to a permission request | Returns `boolean` | +| Метод | Описание | Примечания | +| ---------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | List sessions | Returns Session[] | +| `session.get({ path })` | Get session | Returns Session | +| `session.children({ path })` | List child sessions | Returns Session[] | +| `session.create({ body })` | Create session | Returns Session | +| `session.delete({ path })` | Delete session | Returns `boolean` | +| `session.update({ path, body })` | Update session properties | Returns Session | +| `session.init({ path, body })` | Analyze app and create `AGENTS.md` | Returns `boolean` | +| `session.abort({ path })` | Abort a running session | Returns `boolean` | +| `session.share({ path })` | Share session | Returns Session | +| `session.unshare({ path })` | Unshare session | Returns Session | +| `session.summarize({ path, body })` | Summarize session | Returns `boolean` | +| `session.messages({ path })` | List messages in a session | Returns `{ info: `Message`, parts: `Part[]`}[]` | +| `session.message({ path })` | Get message details | Returns `{ info: `Message`, parts: `Part[]`}` | +| `session.prompt({ path, body })` | Send prompt message | `body.noReply: true` возвращает UserMessage (только контекст). По умолчанию возвращает AssistantMessage с ответом ИИ. Поддерживает `body.outputFormat` для [структурированного вывода](#структурированный-вывод) | +| `session.command({ path, body })` | Send command to session | Returns `{ info: `AssistantMessage`, parts: `Part[]`}` | +| `session.shell({ path, body })` | Run a shell command | Returns AssistantMessage | +| `session.revert({ path, body })` | Revert a message | Returns Session | +| `session.unrevert({ path })` | Restore reverted messages | Returns Session | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | Respond to a permission request | Returns `boolean` | --- diff --git a/packages/web/src/content/docs/ru/server.mdx b/packages/web/src/content/docs/ru/server.mdx index 898789c29a..2356543dff 100644 --- a/packages/web/src/content/docs/ru/server.mdx +++ b/packages/web/src/content/docs/ru/server.mdx @@ -18,13 +18,13 @@ opencode serve [--port ] [--hostname ] [--cors ] #### Параметры -| Флаг | Описание | По умолчанию | -| --------------- | ----------------------------------- | ---------------- | -| `--port` | Port to listen on | `4096` | -| `--hostname` | Hostname to listen on | `127.0.0.1` | -| `--mdns` | Enable mDNS discovery | `false` | -| `--mdns-domain` | Custom domain name for mDNS service | `opencode.local` | -| `--cors` | Additional browser origins to allow | `[]` | +| Флаг | Описание | По умолчанию | +| --------------- | ------------------------------------------- | ---------------- | +| `--port` | Порт для прослушивания | `4096` | +| `--hostname` | Имя хоста для прослушивания | `127.0.0.1` | +| `--mdns` | Включить обнаружение mDNS | `false` | +| `--mdns-domain` | Пользовательское доменное имя для mDNS | `opencode.local` | +| `--cors` | Разрешенные дополнительные источники (CORS) | `[]` | `--cors` можно передать несколько раз: @@ -89,10 +89,10 @@ For example, `http://localhost:4096/doc`. Use the spec to generate clients or in ### Глобальный -| Метод | Путь | Описание | Ответ | -| ----- | ---------------- | ------------------------------ | ------------------------------------ | -| `GET` | `/global/health` | Get server health and version | `{ healthy: true, version: string }` | -| `GET` | `/global/event` | Get global events (SSE stream) | Event stream | +| Метод | Путь | Описание | Ответ | +| ----- | ---------------- | --------------------------------------- | ------------------------------------ | +| `GET` | `/global/health` | Получить состояние и версию сервера | `{ healthy: true, version: string }` | +| `GET` | `/global/event` | Получить глобальные события (поток SSE) | Поток событий | --- @@ -100,105 +100,105 @@ For example, `http://localhost:4096/doc`. Use the spec to generate clients or in | Метод | Путь | Описание | Ответ | | ----- | ------------------ | ----------------------- | --------------------------------------------- | -| `GET` | `/project` | List all projects | Project[] | -| `GET` | `/project/current` | Get the current project | Project | +| `GET` | `/project` | Список всех проектов | Project[] | +| `GET` | `/project/current` | Получить текущий проект | Project | --- ### Путь и система контроля версий -| Метод | Путь | Описание | Ответ | -| ----- | ------- | ------------------------------------ | ------------------------------------------- | -| `GET` | `/path` | Get the current path | Path | -| `GET` | `/vcs` | Get VCS info for the current project | VcsInfo | +| Метод | Путь | Описание | Ответ | +| ----- | ------- | ---------------------------------------------- | ------------------------------------------- | +| `GET` | `/path` | Получить текущий путь | Path | +| `GET` | `/vcs` | Получить информацию о VCS для текущего проекта | VcsInfo | --- ### Экземпляр -| Метод | Путь | Описание | Ответ | -| ------ | ------------------- | ---------------------------- | --------- | -| `POST` | `/instance/dispose` | Dispose the current instance | `boolean` | +| Метод | Путь | Описание | Ответ | +| ------ | ------------------- | ------------------------- | --------- | +| `POST` | `/instance/dispose` | Удалить текущий экземпляр | `boolean` | --- ### Конфигурация -| Метод | Путь | Описание | Ответ | -| ------- | ------------------- | --------------------------------- | ---------------------------------------------------------------------------------------- | -| `GET` | `/config` | Get config info | Config | -| `PATCH` | `/config` | Update config | Config | -| `GET` | `/config/providers` | List providers and default models | `{ providers: `Provider[]`, default: { [key: string]: string } }` | +| Метод | Путь | Описание | Ответ | +| ------- | ------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------- | +| `GET` | `/config` | Получить информацию о конфигурации | Config | +| `PATCH` | `/config` | Обновить конфигурацию | Config | +| `GET` | `/config/providers` | Список провайдеров и моделей по умолчанию | `{ providers: `Provider[]`, default: { [key: string]: string } }` | --- ### Поставщик -| Метод | Путь | Описание | Ответ | -| ------ | -------------------------------- | ------------------------------------ | ----------------------------------------------------------------------------------- | -| `GET` | `/provider` | List all providers | `{ all: `Provider[]`, default: {...}, connected: string[] }` | -| `GET` | `/provider/auth` | Get provider authentication methods | `{ [providerID: string]: `ProviderAuthMethod[]` }` | -| `POST` | `/provider/{id}/oauth/authorize` | Authorize a provider using OAuth | ProviderAuthAuthorization | -| `POST` | `/provider/{id}/oauth/callback` | Handle OAuth callback for a provider | `boolean` | +| Метод | Путь | Описание | Ответ | +| ------ | -------------------------------- | ----------------------------------------- | ----------------------------------------------------------------------------------- | +| `GET` | `/provider` | Список всех провайдеров | `{ all: `Provider[]`, default: {...}, connected: string[] }` | +| `GET` | `/provider/auth` | Получить методы аутентификации провайдера | `{ [providerID: string]: `ProviderAuthMethod[]` }` | +| `POST` | `/provider/{id}/oauth/authorize` | Авторизация провайдера через OAuth | ProviderAuthAuthorization | +| `POST` | `/provider/{id}/oauth/callback` | Обработка callback OAuth для провайдера | `boolean` | --- ### Сессии -| Метод | Путь | Описание | Примечания | -| -------- | ---------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------- | -| `GET` | `/session` | List all sessions | Returns Session[] | -| `POST` | `/session` | Create a new session | body: `{ parentID?, title? }`, returns Session | -| `GET` | `/session/status` | Get session status for all sessions | Returns `{ [sessionID: string]: `SessionStatus` }` | -| `GET` | `/session/:id` | Get session details | Returns Session | -| `DELETE` | `/session/:id` | Delete a session and all its data | Returns `boolean` | -| `PATCH` | `/session/:id` | Update session properties | body: `{ title? }`, returns Session | -| `GET` | `/session/:id/children` | Get a session's child sessions | Returns Session[] | -| `GET` | `/session/:id/todo` | Get the todo list for a session | Returns Todo[] | -| `POST` | `/session/:id/init` | Analyze app and create `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returns `boolean` | -| `POST` | `/session/:id/fork` | Fork an existing session at a message | body: `{ messageID? }`, returns Session | -| `POST` | `/session/:id/abort` | Abort a running session | Returns `boolean` | -| `POST` | `/session/:id/share` | Share a session | Returns Session | -| `DELETE` | `/session/:id/share` | Unshare a session | Returns Session | -| `GET` | `/session/:id/diff` | Get the diff for this session | query: `messageID?`, returns FileDiff[] | -| `POST` | `/session/:id/summarize` | Summarize the session | body: `{ providerID, modelID }`, returns `boolean` | -| `POST` | `/session/:id/revert` | Revert a message | body: `{ messageID, partID? }`, returns `boolean` | -| `POST` | `/session/:id/unrevert` | Restore all reverted messages | Returns `boolean` | -| `POST` | `/session/:id/permissions/:permissionID` | Respond to a permission request | body: `{ response, remember? }`, returns `boolean` | +| Метод | Путь | Описание | Примечания | +| -------- | ---------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------- | +| `GET` | `/session` | Список всех сессий | Возвращает Session[] | +| `POST` | `/session` | Создать новую сессию | body: `{ parentID?, title? }`, возвращает Session | +| `GET` | `/session/status` | Получить статус всех сессий | Возвращает `{ [sessionID: string]: `SessionStatus` }` | +| `GET` | `/session/:id` | Получить детали сессии | Возвращает Session | +| `DELETE` | `/session/:id` | Удалить сессию и все её данные | Возвращает `boolean` | +| `PATCH` | `/session/:id` | Обновить свойства сессии | body: `{ title? }`, возвращает Session | +| `GET` | `/session/:id/children` | Получить дочерние сессии | Возвращает Session[] | +| `GET` | `/session/:id/todo` | Получить список задач для сессии | Возвращает Todo[] | +| `POST` | `/session/:id/init` | Анализ приложения и создание `AGENTS.md` | body: `{ messageID, providerID, modelID }`, возвращает `boolean` | +| `POST` | `/session/:id/fork` | Ответвление сессии от сообщения | body: `{ messageID? }`, возвращает Session | +| `POST` | `/session/:id/abort` | Прервать запущенную сессию | Возвращает `boolean` | +| `POST` | `/session/:id/share` | Поделиться сессией | Возвращает Session | +| `DELETE` | `/session/:id/share` | Отменить общий доступ к сессии | Возвращает Session | +| `GET` | `/session/:id/diff` | Получить diff для этой сессии | query: `messageID?`, возвращает FileDiff[] | +| `POST` | `/session/:id/summarize` | Суммировать сессию | body: `{ providerID, modelID }`, возвращает `boolean` | +| `POST` | `/session/:id/revert` | Отменить сообщение | body: `{ messageID, partID? }`, возвращает `boolean` | +| `POST` | `/session/:id/unrevert` | Восстановить все отмененные сообщения | Возвращает `boolean` | +| `POST` | `/session/:id/permissions/:permissionID` | Ответить на запрос разрешения | body: `{ response, remember? }`, возвращает `boolean` | --- ### Сообщения -| Метод | Путь | Описание | Примечания | -| ------ | --------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `GET` | `/session/:id/message` | List messages in a session | query: `limit?`, returns `{ info: `Message`, parts: `Part[]`}[]` | -| `POST` | `/session/:id/message` | Send a message and wait for response | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returns `{ info: `Message`, parts: `Part[]`}` | -| `GET` | `/session/:id/message/:messageID` | Get message details | Returns `{ info: `Message`, parts: `Part[]`}` | -| `POST` | `/session/:id/prompt_async` | Send a message asynchronously (no wait) | body: same as `/session/:id/message`, returns `204 No Content` | -| `POST` | `/session/:id/command` | Execute a slash command | body: `{ messageID?, agent?, model?, command, arguments }`, returns `{ info: `Message`, parts: `Part[]`}` | -| `POST` | `/session/:id/shell` | Run a shell command | body: `{ agent, model?, command }`, returns `{ info: `Message`, parts: `Part[]`}` | +| Метод | Путь | Описание | Примечания | +| ------ | --------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `GET` | `/session/:id/message` | Список сообщений в сессии | query: `limit?`, возвращает `{ info: `Message`, parts: `Part[]`}[]` | +| `POST` | `/session/:id/message` | Отправить сообщение и ждать ответа | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, возвращает `{ info: `Message`, parts: `Part[]`}` | +| `GET` | `/session/:id/message/:messageID` | Получить детали сообщения | Возвращает `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/prompt_async` | Отправить сообщение асинхронно (без ожидания) | body: как в `/session/:id/message`, возвращает `204 No Content` | +| `POST` | `/session/:id/command` | Выполнить слэш-команду | body: `{ messageID?, agent?, model?, command, arguments }`, возвращает `{ info: `Message`, parts: `Part[]`}` | +| `POST` | `/session/:id/shell` | Запустить команду оболочки | body: `{ agent, model?, command }`, возвращает `{ info: `Message`, parts: `Part[]`}` | --- ### Команды -| Метод | Путь | Описание | Ответ | -| ----- | ---------- | ----------------- | --------------------------------------------- | -| `GET` | `/command` | List all commands | Command[] | +| Метод | Путь | Описание | Ответ | +| ----- | ---------- | ------------------ | --------------------------------------------- | +| `GET` | `/command` | Список всех команд | Command[] | --- ### Файлы -| Метод | Путь | Описание | Ответ | -| ----- | ------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------- | -| `GET` | `/find?pattern=` | Search for text in files | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | -| `GET` | `/find/file?query=` | Find files and directories by name | `string[]` (paths) | -| `GET` | `/find/symbol?query=` | Find workspace symbols | Symbol[] | -| `GET` | `/file?path=` | List files and directories | FileNode[] | -| `GET` | `/file/content?path=

` | Read a file | FileContent | -| `GET` | `/file/status` | Get status for tracked files | File[] | +| Метод | Путь | Описание | Ответ | +| ----- | ------------------------ | ------------------------------------ | -------------------------------------------------------------------------------------------- | +| `GET` | `/find?pattern=` | Поиск текста в файлах | Массив объектов совпадения с `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | +| `GET` | `/find/file?query=` | Поиск файлов и директорий по имени | `string[]` (пути) | +| `GET` | `/find/symbol?query=` | Поиск символов рабочего пространства | Symbol[] | +| `GET` | `/file?path=` | Список файлов и директорий | FileNode[] | +| `GET` | `/file/content?path=

` | Прочитать файл | FileContent | +| `GET` | `/file/status` | Получить статус отслеживаемых файлов | File[] | #### `/find/file` параметры запроса @@ -212,76 +212,76 @@ For example, `http://localhost:4096/doc`. Use the spec to generate clients or in ### Инструменты (Экспериментальные) -| Метод | Путь | Описание | Ответ | -| ----- | ------------------------------------------- | ---------------------------------------- | -------------------------------------------- | -| `GET` | `/experimental/tool/ids` | List all tool IDs | ToolIDs | -| `GET` | `/experimental/tool?provider=

&model=` | List tools with JSON schemas for a model | ToolList | +| Метод | Путь | Описание | Ответ | +| ----- | ------------------------------------------- | ---------------------------------------------- | -------------------------------------------- | +| `GET` | `/experimental/tool/ids` | Список всех идентификаторов инструментов | ToolIDs | +| `GET` | `/experimental/tool?provider=

&model=` | Список инструментов со схемами JSON для модели | ToolList | --- ### LSP, форматтеры и MCP -| Метод | Путь | Описание | Ответ | -| ------ | ------------ | -------------------------- | -------------------------------------------------------- | -| `GET` | `/lsp` | Get LSP server status | LSPStatus[] | -| `GET` | `/formatter` | Get formatter status | FormatterStatus[] | -| `GET` | `/mcp` | Get MCP server status | `{ [name: string]: `MCPStatus` }` | -| `POST` | `/mcp` | Add MCP server dynamically | body: `{ name, config }`, returns MCP status object | +| Метод | Путь | Описание | Ответ | +| ------ | ------------ | ------------------------------- | -------------------------------------------------------- | +| `GET` | `/lsp` | Получить статус сервера LSP | LSPStatus[] | +| `GET` | `/formatter` | Получить статус форматера | FormatterStatus[] | +| `GET` | `/mcp` | Получить статус сервера MCP | `{ [name: string]: `MCPStatus` }` | +| `POST` | `/mcp` | Добавить сервер MCP динамически | body: `{ name, config }`, возвращает статус объекта MCP | --- ### Агенты -| Метод | Путь | Описание | Ответ | -| ----- | -------- | ------------------------- | ------------------------------------------- | -| `GET` | `/agent` | List all available agents | Agent[] | +| Метод | Путь | Описание | Ответ | +| ----- | -------- | ----------------------------- | ------------------------------------------- | +| `GET` | `/agent` | Список всех доступных агентов | Agent[] | --- ### Ведение журнала -| Метод | Путь | Описание | Ответ | -| ------ | ------ | ------------------------------------------------------------ | --------- | -| `POST` | `/log` | Write log entry. Body: `{ service, level, message, extra? }` | `boolean` | +| Метод | Путь | Описание | Ответ | +| ------ | ------ | --------------------------------------------------------------------- | --------- | +| `POST` | `/log` | Записать запись в журнал. Body: `{ service, level, message, extra? }` | `boolean` | --- ### TUI -| Метод | Путь | Описание | Ответ | -| ------ | ----------------------- | ------------------------------------------- | ---------------------- | -| `POST` | `/tui/append-prompt` | Append text to the prompt | `boolean` | -| `POST` | `/tui/open-help` | Open the help dialog | `boolean` | -| `POST` | `/tui/open-sessions` | Open the session selector | `boolean` | -| `POST` | `/tui/open-themes` | Open the theme selector | `boolean` | -| `POST` | `/tui/open-models` | Open the model selector | `boolean` | -| `POST` | `/tui/submit-prompt` | Submit the current prompt | `boolean` | -| `POST` | `/tui/clear-prompt` | Clear the prompt | `boolean` | -| `POST` | `/tui/execute-command` | Execute a command (`{ command }`) | `boolean` | -| `POST` | `/tui/show-toast` | Show toast (`{ title?, message, variant }`) | `boolean` | -| `GET` | `/tui/control/next` | Wait for the next control request | Control request object | -| `POST` | `/tui/control/response` | Respond to a control request (`{ body }`) | `boolean` | +| Метод | Путь | Описание | Ответ | +| ------ | ----------------------- | ----------------------------------------------------- | ------------------------- | +| `POST` | `/tui/append-prompt` | Добавить текст в подсказку | `boolean` | +| `POST` | `/tui/open-help` | Открыть диалог помощи | `boolean` | +| `POST` | `/tui/open-sessions` | Открыть селектор сессий | `boolean` | +| `POST` | `/tui/open-themes` | Открыть селектор тем | `boolean` | +| `POST` | `/tui/open-models` | Открыть селектор моделей | `boolean` | +| `POST` | `/tui/submit-prompt` | Отправить текущую подсказку | `boolean` | +| `POST` | `/tui/clear-prompt` | Очистить подсказку | `boolean` | +| `POST` | `/tui/execute-command` | Выполнить команду (`{ command }`) | `boolean` | +| `POST` | `/tui/show-toast` | Показать уведомление (`{ title?, message, variant }`) | `boolean` | +| `GET` | `/tui/control/next` | Ожидание следующего запроса управления | Объект запроса управления | +| `POST` | `/tui/control/response` | Ответить на запрос управления (`{ body }`) | `boolean` | --- ### Авторизация -| Метод | Путь | Описание | Ответ | -| ----- | ----------- | --------------------------------------------------------------- | --------- | -| `PUT` | `/auth/:id` | Set authentication credentials. Body must match provider schema | `boolean` | +| Метод | Путь | Описание | Ответ | +| ----- | ----------- | -------------------------------------------------------------------------------------- | --------- | +| `PUT` | `/auth/:id` | Установить учетные данные аутентификации. Body должен соответствовать схеме провайдера | `boolean` | --- ### События -| Метод | Путь | Описание | Ответ | -| ----- | -------- | ----------------------------------------------------------------------------- | ------------------------- | -| `GET` | `/event` | Server-sent events stream. First event is `server.connected`, then bus events | Server-sent events stream | +| Метод | Путь | Описание | Ответ | +| ----- | -------- | --------------------------------------------------------------------------------------------- | ------------------------------------ | +| `GET` | `/event` | Поток событий, отправляемых сервером. Первое событие — `server.connected`, затем события шины | Поток событий, отправляемых сервером | --- ### Документы -| Метод | Путь | Описание | Ответ | -| ----- | ------ | ------------------------- | --------------------------- | -| `GET` | `/doc` | OpenAPI 3.1 specification | HTML page with OpenAPI spec | +| Метод | Путь | Описание | Ответ | +| ----- | ------ | ------------------------ | -------------------------------------- | +| `GET` | `/doc` | Спецификация OpenAPI 3.1 | HTML-страница со спецификацией OpenAPI | diff --git a/packages/web/src/content/docs/ru/themes.mdx b/packages/web/src/content/docs/ru/themes.mdx index 2e5219e4c5..05ace2c7b8 100644 --- a/packages/web/src/content/docs/ru/themes.mdx +++ b/packages/web/src/content/docs/ru/themes.mdx @@ -61,11 +61,11 @@ opencode поставляется с несколькими встроенным ## Использование темы -Вы можете выбрать тему, вызвав выбор темы с помощью команды `/theme`. Или вы можете указать это в файле [config](/docs/config). +Вы можете выбрать тему, вызвав выбор темы с помощью команды `/theme`. Или вы можете указать это в файле [tui.json](/docs/config#tui). -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` diff --git a/packages/web/src/content/docs/ru/tui.mdx b/packages/web/src/content/docs/ru/tui.mdx index 0134e29c48..1694908dba 100644 --- a/packages/web/src/content/docs/ru/tui.mdx +++ b/packages/web/src/content/docs/ru/tui.mdx @@ -355,24 +355,34 @@ How is auth handled in @packages/functions/src/api/index.ts? ## Настройка -Вы можете настроить поведение TUI через файл конфигурации opencode. +Вы можете настроить поведение TUI через `tui.json` (или `tui.jsonc`). -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +Это отдельный файл от `opencode.json`, который настраивает поведение сервера/выполнения. + ### Параметры -- `scroll_acceleration` — включите ускорение прокрутки в стиле macOS для плавной и естественной прокрутки. Если этот параметр включен, скорость прокрутки увеличивается при быстрой прокрутке и остается точной при более медленных движениях. **Этот параметр имеет приоритет над `scroll_speed` и переопределяет его, если он включен.** -- `scroll_speed` — контролирует скорость прокрутки TUI при использовании команд прокрутки (минимум: `1`). По умолчанию `3`. **Примечание. Это игнорируется, если для `scroll_acceleration.enabled` установлено значение `true`.** +- `theme` — Устанавливает тему пользовательского интерфейса. [Подробнее](/docs/themes). +- `keybinds` — Настраивает сочетания клавиш. [Подробнее](/docs/keybinds). +- `scroll_acceleration.enabled` — включите ускорение прокрутки в стиле macOS для плавной и естественной прокрутки. Если этот параметр включен, скорость прокрутки увеличивается при быстрой прокрутке и остается точной при более медленных движениях. **Этот параметр имеет приоритет над `scroll_speed` и переопределяет его, если он включен.** +- `scroll_speed` — контролирует скорость прокрутки TUI при использовании команд прокрутки (минимум: `0.001`, поддерживает десятичные значения). По умолчанию `3`. **Примечание. Это игнорируется, если для `scroll_acceleration.enabled` установлено значение `true`.** +- `diff_style` — Управляет отображением различий. `"auto"` адаптируется к ширине терминала, `"stacked"` всегда показывает одноколоночный макет. + +Используйте `OPENCODE_TUI_CONFIG` для загрузки пользовательского пути конфигурации TUI. --- diff --git a/packages/web/src/content/docs/ru/zen.mdx b/packages/web/src/content/docs/ru/zen.mdx index 3fe03a47fa..078d1a3819 100644 --- a/packages/web/src/content/docs/ru/zen.mdx +++ b/packages/web/src/content/docs/ru/zen.mdx @@ -63,6 +63,7 @@ OpenCode Zen работает так же, как и любой другой п | Модель | Идентификатор модели | Конечная точка | Пакет AI SDK | | ------------------ | -------------------- | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -72,13 +73,15 @@ OpenCode Zen работает так же, как и любой другой п | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | | MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -86,10 +89,8 @@ OpenCode Zen работает так же, как и любой другой п | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -123,27 +124,29 @@ https://opencode.ai/zen/v1/models | MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | | GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | -| GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| GLM 4.7 Free | Бесплатно | Бесплатно | Бесплатно | - | -| Kimi K2.5 Free | Бесплатно | Бесплатно | Бесплатно | - | | Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - | +| Claude Opus 4.6 (≤ 200 тыс. токенов) | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.6 (> 200 тыс. токенов) | $10.00 | $37.50 | $1.00 | $12.50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Claude Sonnet 4.6 (≤ 200 тыс. токенов) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.6 (> 200 тыс. токенов) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4.5 (≤ 200 тыс. токенов) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4.5 (> 200 тыс. токенов) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (≤ 200 тыс. токенов) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (> 200 тыс. токенов) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | -| Claude Opus 4.6 (≤ 200 тыс. токенов) | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.6 (> 200 тыс. токенов) | $10.00 | $37.50 | $1.00 | $12.50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Gemini 3.1 Pro (≤ 200 тыс. токенов) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3.1 Pro (> 200 тыс. токенов) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Pro (≤ 200 тыс. токенов) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200 тыс. токенов) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - | @@ -162,7 +165,6 @@ https://opencode.ai/zen/v1/models Бесплатные модели: -- Kimi K2.5 Free доступен на OpenCode в течение ограниченного времени. Команда использует это время для сбора отзывов и улучшения модели. - MiniMax M2.5 Free доступен на OpenCode в течение ограниченного времени. Команда использует это время для сбора отзывов и улучшения модели. - Big Pickle — это стелс-модель, которая доступна бесплатно на OpenCode в течение ограниченного времени. Команда использует это время для сбора отзывов и улучшения модели. @@ -194,7 +196,6 @@ https://opencode.ai/zen/v1/models Все наши модели размещены в США. Наши поставщики придерживаются политики нулевого хранения и не используют ваши данные для обучения моделей, за следующими исключениями: - Big Pickle: во время бесплатного периода собранные данные могут быть использованы для улучшения модели. -- Kimi K2.5 Free: в течение бесплатного периода собранные данные могут использоваться для улучшения модели. - MiniMax M2.5 Free: в течение бесплатного периода собранные данные могут использоваться для улучшения модели. - API OpenAI: запросы хранятся в течение 30 дней в соответствии с [Политикой данных OpenAI](https://platform.openai.com/docs/guides/your-data). - API-интерфейсы Anthropic: запросы хранятся в течение 30 дней в соответствии с [Политикой данных Anthropic](https://docs.anthropic.com/en/docs/claude-code/data-usage). diff --git a/packages/web/src/content/docs/th/cli.mdx b/packages/web/src/content/docs/th/cli.mdx index 60e3fac764..875f517fc2 100644 --- a/packages/web/src/content/docs/th/cli.mdx +++ b/packages/web/src/content/docs/th/cli.mdx @@ -559,6 +559,7 @@ OpenCode สามารถกำหนดค่าโดยใช้ตัว | `OPENCODE_AUTO_SHARE` | Boolean | แชร์เซสชันอัตโนมัติเมื่อสร้าง | | `OPENCODE_GIT_BASH_PATH` | String | เส้นทางไปยัง Git Bash บน Windows | | `OPENCODE_CONFIG` | String | เส้นทางไปยังไฟล์การกำหนดค่า | +| `OPENCODE_TUI_CONFIG` | String | เส้นทางไปยังไฟล์การกำหนดค่า TUI | | `OPENCODE_CONFIG_DIR` | String | เส้นทางไปยังไดเร็กทอรีการกำหนดค่า | | `OPENCODE_CONFIG_CONTENT` | String | เนื้อหาการกำหนดค่าแบบ inline JSON | | `OPENCODE_DISABLE_AUTOUPDATE` | Boolean | ปิดใช้งานการอัปเดตอัตโนมัติ | diff --git a/packages/web/src/content/docs/th/config.mdx b/packages/web/src/content/docs/th/config.mdx index 06836aca3b..c58469c77a 100644 --- a/packages/web/src/content/docs/th/config.mdx +++ b/packages/web/src/content/docs/th/config.mdx @@ -14,10 +14,11 @@ OpenCode รองรับทั้งรูปแบบ **JSON** และ **J ```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", - // Theme configuration - "theme": "opencode", "model": "anthropic/claude-sonnet-4-5", "autoupdate": true, + "server": { + "port": 4096, + }, } ``` @@ -34,7 +35,7 @@ OpenCode รองรับทั้งรูปแบบ **JSON** และ **J ไฟล์การกำหนดค่าจะถูกรวมเข้าด้วยกัน โดยไม่มีการแทนที่ การตั้งค่าจากตำแหน่งการกำหนดค่าต่อไปนี้จะรวมกัน การกำหนดค่าในภายหลังจะแทนที่การกำหนดค่าก่อนหน้าสำหรับคีย์ที่ขัดแย้งกันเท่านั้น การตั้งค่าที่ไม่ขัดแย้งจากการกำหนดค่าทั้งหมดจะยังคงอยู่ -ตัวอย่างเช่น หากการกำหนดค่าส่วนกลางของคุณตั้งค่า `theme: "opencode"` และ `autoupdate: true` และการกำหนดค่าโปรเจ็กต์ของคุณตั้งค่า `model: "anthropic/claude-sonnet-4-5"` การกำหนดค่าสุดท้ายจะรวมการตั้งค่าทั้งสามรายการไว้ด้วย +ตัวอย่างเช่น หากการกำหนดค่าส่วนกลางของคุณตั้งค่า `autoupdate: true` และการกำหนดค่าโปรเจ็กต์ของคุณตั้งค่า `model: "anthropic/claude-sonnet-4-5"` การกำหนดค่าสุดท้ายจะรวมการตั้งค่าทั้งสองรายการไว้ด้วย --- @@ -95,7 +96,9 @@ OpenCode รองรับทั้งรูปแบบ **JSON** และ **J ### ทั่วโลก -วางการกำหนดค่า OpenCode ส่วนกลางของคุณใน `~/.config/opencode/opencode.json` ใช้การกำหนดค่าส่วนกลางสำหรับการตั้งค่าทั้งผู้ใช้ เช่น ธีม ผู้ให้บริการ หรือปุ่มลัด +วางการกำหนดค่า OpenCode ส่วนกลางของคุณใน `~/.config/opencode/opencode.json` ใช้การกำหนดค่าส่วนกลางสำหรับการตั้งค่าทั้งผู้ใช้ เช่น ผู้ให้บริการ รุ่น และสิทธิ์ + +สำหรับการตั้งค่าเฉพาะ TUI ให้ใช้ `~/.config/opencode/tui.json` การกำหนดค่าส่วนกลางจะแทนที่ค่าเริ่มต้นขององค์กรระยะไกล @@ -105,6 +108,8 @@ OpenCode รองรับทั้งรูปแบบ **JSON** และ **J เพิ่ม `opencode.json` ในรูทโปรเจ็กต์ของคุณ การกำหนดค่าโปรเจ็กต์มีความสำคัญสูงสุดในบรรดาไฟล์กำหนดค่ามาตรฐาน โดยจะแทนที่การกำหนดค่าทั้งส่วนกลางและระยะไกล +สำหรับการตั้งค่า TUI เฉพาะโครงการ ให้เพิ่ม `tui.json` ควบคู่ไปกับมัน + :::tip วางการกำหนดค่าเฉพาะโปรเจ็กต์ไว้ที่รากของโปรเจ็กต์ของคุณ ::: @@ -148,34 +153,32 @@ opencode run "Hello world" ไฟล์กำหนดค่ามีสคีมาที่กำหนดไว้ใน [**`opencode.ai/config.json`**](https://opencode.ai/config.json) +การกำหนดค่า TUI ใช้ [**`opencode.ai/tui.json`**](https://opencode.ai/tui.json) + ผู้แก้ไขของคุณควรสามารถตรวจสอบและเติมข้อความอัตโนมัติตามสคีมาได้ --- ### TUI -คุณสามารถกำหนดการตั้งค่าเฉพาะ TUI ผ่านตัวเลือก `tui` +ใช้ไฟล์ `tui.json` (หรือ `tui.jsonc`) เฉพาะสำหรับการตั้งค่าเฉพาะ TUI -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - }, - "diff_style": "auto" - } + "$schema": "https://opencode.ai/tui.json", + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` -ตัวเลือกที่มี: +ใช้ `OPENCODE_TUI_CONFIG` เพื่อชี้ไปยังไฟล์กำหนดค่า TUI ที่กำหนดเอง -- `scroll_acceleration.enabled` - ​​เปิดใช้งานการเร่งความเร็วการเลื่อนแบบ macOS **มีลำดับความสำคัญมากกว่า `scroll_speed`.** -- `scroll_speed` - ​​ตัวคูณความเร็วการเลื่อนแบบกำหนดเอง (ค่าเริ่มต้น: `3` ขั้นต่ำ: `1`) ไม่สนใจหาก `scroll_acceleration.enabled` คือ `true` -- `diff_style` - ​​ควบคุมการเรนเดอร์ต่าง `"auto"` ปรับให้เข้ากับความกว้างของ terminal `"stacked"` จะแสดงคอลัมน์เดียวเสมอ +คีย์ `theme`, `keybinds` และ `tui` แบบเดิมใน `opencode.json` เลิกใช้แล้วและจะถูกย้ายโดยอัตโนมัติเมื่อเป็นไปได้ -[เรียนรู้เพิ่มเติมเกี่ยวกับการใช้ TUI ที่นี่](/docs/tui) +[เรียนรู้เพิ่มเติมเกี่ยวกับการใช้ TUI ที่นี่](/docs/tui#configure) --- @@ -301,12 +304,12 @@ Bearer Token (`AWS_BEARER_TOKEN_BEDROCK` หรือ `/connect`) มีคว ### Themes -คุณสามารถกำหนดค่าธีมที่คุณต้องการใช้ในการกำหนดค่า OpenCode ของคุณได้ผ่านตัวเลือก `theme` +ตั้งค่าธีม UI ของคุณใน `tui.json` -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "theme": "" + "$schema": "https://opencode.ai/tui.json", + "theme": "tokyonight" } ``` @@ -406,11 +409,11 @@ Bearer Token (`AWS_BEARER_TOKEN_BEDROCK` หรือ `/connect`) มีคว ### คีย์ลัด -คุณสามารถปรับแต่งปุ่มลัดของคุณได้ผ่านตัวเลือก `keybinds` +ปรับแต่งปุ่มลัดใน `tui.json` -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": {} } ``` @@ -490,13 +493,15 @@ OpenCode จะดาวน์โหลดการอัปเดตใหม "$schema": "https://opencode.ai/config.json", "compaction": { "auto": true, - "prune": true + "prune": true, + "reserved": 10000 } } ``` - `auto` - ​​กระชับเซสชันโดยอัตโนมัติเมื่อบริบทเต็ม (ค่าเริ่มต้น: `true`) - `prune` - ​​ลบเอาท์พุตเครื่องมือเก่าเพื่อบันทึก tokens (ค่าเริ่มต้น: `true`) +- `reserved` - บัฟเฟอร์โทเค็นสำหรับการบีบอัด ให้หน้าต่างเพียงพอเพื่อหลีกเลี่ยงการล้นระหว่างการบีบอัด --- diff --git a/packages/web/src/content/docs/th/custom-tools.mdx b/packages/web/src/content/docs/th/custom-tools.mdx index 28cd229cfd..c5e6385357 100644 --- a/packages/web/src/content/docs/th/custom-tools.mdx +++ b/packages/web/src/content/docs/th/custom-tools.mdx @@ -79,6 +79,32 @@ export const multiply = tool({ --- +#### ชื่อซ้ำกับเครื่องมือในตัว + +เครื่องมือแบบกำหนดเองจะถูกระบุด้วยชื่อเครื่องมือ หากเครื่องมือแบบกำหนดเองใช้ชื่อเดียวกับเครื่องมือในตัว เครื่องมือแบบกำหนดเองจะมีความสำคัญเหนือกว่า + +ตัวอย่างเช่น ไฟล์นี้จะแทนที่เครื่องมือ `bash` ในตัว: + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +ชอบชื่อที่ไม่ซ้ำกันเว้นแต่คุณตั้งใจจะแทนที่เครื่องมือในตัว หากคุณต้องการปิดใช้งานเครื่องมือในตัวแต่ไม่ต้องการแทนที่ ให้ใช้ [permissions](/docs/permissions) +::: + +--- + ### ข้อโต้แย้ง คุณสามารถใช้ `tool.schema` ซึ่งก็คือ [Zod](https://zod.dev) เพื่อกำหนดประเภทอาร์กิวเมนต์ diff --git a/packages/web/src/content/docs/th/go.mdx b/packages/web/src/content/docs/th/go.mdx new file mode 100644 index 0000000000..7dcaf398a5 --- /dev/null +++ b/packages/web/src/content/docs/th/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: การสมัครสมาชิกราคาประหยัดสำหรับโมเดลการเขียนโค้ดแบบเปิด +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go คือการสมัครสมาชิกราคาประหยัดเพียง **$10/เดือน** ที่ให้คุณเข้าถึงโมเดลการเขียนโค้ดแบบเปิดยอดนิยมได้อย่างน่าเชื่อถือ + +:::note +ขณะนี้ OpenCode Go อยู่ในช่วงเบต้า +::: + +Go ทำงานเหมือนกับผู้ให้บริการรายอื่นใน OpenCode คุณสมัครสมาชิก OpenCode Go และรับคีย์ API ของคุณ มันเป็น**ตัวเลือกเสริมทั้งหมด** และคุณไม่จำเป็นต้องใช้มันเพื่อใช้งาน OpenCode + +มันถูกออกแบบมาสำหรับผู้ใช้งานระดับนานาชาติเป็นหลัก โดยมีโมเดลโฮสต์อยู่ในสหรัฐอเมริกา สหภาพยุโรป และสิงคโปร์ เพื่อการเข้าถึงที่เสถียรทั่วโลก + +--- + +## ความเป็นมา + +โมเดลแบบเปิดมีคุณภาพดีขึ้นมาก ปัจจุบันมีประสิทธิภาพใกล้เคียงกับโมเดลที่เป็นกรรมสิทธิ์สำหรับงานเขียนโค้ด และเนื่องจากผู้ให้บริการหลายรายสามารถให้บริการโมเดลเหล่านี้ได้อย่างแข่งขันกัน จึงมักจะมีราคาถูกกว่ามาก + +อย่างไรก็ตาม การเข้าถึงโมเดลเหล่านี้อย่างน่าเชื่อถือและมีความหน่วงต่ำอาจเป็นเรื่องยาก ผู้ให้บริการมีคุณภาพและความพร้อมใช้งานที่แตกต่างกัน + +:::tip +เราได้ทดสอบกลุ่มโมเดลและผู้ให้บริการที่เลือกสรรแล้วซึ่งทำงานได้ดีกับ OpenCode +::: + +เพื่อแก้ไขปัญหานี้ เราได้ทำสิ่งต่อไปนี้: + +1. เราทดสอบกลุ่มโมเดลแบบเปิดที่เลือกสรรและพูดคุยกับทีมของพวกเขาเกี่ยวกับวิธีการรันโมเดลให้ดีที่สุด +2. จากนั้นเราทำงานร่วมกับผู้ให้บริการบางรายเพื่อให้แน่ใจว่าโมเดลเหล่านี้ได้รับการให้บริการอย่างถูกต้อง +3. สุดท้าย เราทำการทดสอบประสิทธิภาพ (Benchmark) การรวมกันของโมเดล/ผู้ให้บริการ และได้รายชื่อที่เรารู้สึกดีที่จะแนะนำ + +OpenCode Go ให้คุณเข้าถึงโมเดลเหล่านี้ในราคา **$10/เดือน** + +--- + +## วิธีการทำงาน + +OpenCode Go ทำงานเหมือนกับผู้ให้บริการรายอื่นใน OpenCode + +1. ลงชื่อเข้าใช้ **OpenCode Zen** สมัครสมาชิก Go และคัดลอกคีย์ API ของคุณ +2. รันคำสั่ง `/connect` ใน TUI เลือก `OpenCode Go` และวางคีย์ API ของคุณ +3. รัน `/models` ใน TUI เพื่อดูรายชื่อโมเดลที่สามารถใช้งานได้ผ่าน Go + +:::note +สมาชิกเพียงหนึ่งคนต่อพื้นที่ทำงาน (Workspace) เท่านั้นที่สามารถสมัครสมาชิก OpenCode Go ได้ +::: + +รายชื่อโมเดลปัจจุบันประกอบด้วย: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +รายชื่อโมเดลอาจมีการเปลี่ยนแปลงเมื่อเราทดสอบและเพิ่มโมเดลใหม่ + +--- + +## ขีดจำกัดการใช้งาน + +OpenCode Go มีขีดจำกัดดังต่อไปนี้: + +- **ขีดจำกัด 5 ชั่วโมง** — การใช้งานมูลค่า $12 +- **ขีดจำกัดรายสัปดาห์** — การใช้งานมูลค่า $30 +- **ขีดจำกัดรายเดือน** — การใช้งานมูลค่า $60 + +ขีดจำกัดถูกกำหนดเป็นมูลค่าดอลลาร์ ซึ่งหมายความว่าจำนวนคำขอจริงของคุณจะขึ้นอยู่กับโมเดลที่คุณใช้ โมเดลที่ถูกกว่าเช่น MiniMax M2.5 อนุญาตให้ส่งคำขอได้มากกว่า ในขณะที่โมเดลที่มีราคาสูงกว่าเช่น GLM-5 จะอนุญาตให้ส่งคำขอได้น้อยกว่า + +ตารางด้านล่างแสดงจำนวนคำขอโดยประมาณตามรูปแบบการใช้งาน Go ทั่วไป: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ----------------- | ----- | --------- | ------------ | +| คำขอต่อ 5 ชั่วโมง | 1,150 | 1,850 | 30,000 | +| คำขอต่อสัปดาห์ | 2,880 | 4,630 | 75,000 | +| คำขอต่อเดือน | 5,750 | 9,250 | 150,000 | + +การประมาณการขึ้นอยู่กับรูปแบบคำขอเฉลี่ยที่สังเกตได้: + +- GLM-5 — 700 input, 52,000 cached, 150 output tokens ต่อคำขอ +- Kimi K2.5 — 870 input, 55,000 cached, 200 output tokens ต่อคำขอ +- MiniMax M2.5 — 300 input, 55,000 cached, 125 output tokens ต่อคำขอ + +คุณสามารถติดตามการใช้งานปัจจุบันของคุณได้ใน **คอนโซล** + +:::tip +หากคุณใช้งานจนถึงขีดจำกัด คุณสามารถใช้โมเดลฟรีต่อไปได้ +::: + +ขีดจำกัดการใช้งานอาจมีการเปลี่ยนแปลงเมื่อเราเรียนรู้จากการใช้งานและข้อเสนอแนะในช่วงแรก + +--- + +### ราคา + +OpenCode Go เป็นแผนการสมัครสมาชิกราคา **$10/เดือน** ด้านล่างคือราคา**ต่อ 1 ล้านโทเค็น** + +| Model | Input | Output | Cached Read | +| ------------ | ----- | ------ | ----------- | +| GLM-5 | $1.00 | $3.20 | $0.20 | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | +| MiniMax M2.5 | $0.30 | $1.20 | $0.03 | + +--- + +### การใช้งานเกินขีดจำกัด + +หากคุณมีเครดิตในยอดคงเหลือ Zen ของคุณ คุณสามารถเปิดใช้งานตัวเลือก **Use balance** ในคอนโซล เมื่อเปิดใช้งาน Go จะเปลี่ยนไปใช้ยอดคงเหลือ Zen ของคุณหลังจากที่คุณใช้งานถึงขีดจำกัดแล้ว แทนที่จะบล็อกคำขอ + +--- + +## Endpoints + +คุณยังสามารถเข้าถึงโมเดล Go ผ่าน API endpoints ต่อไปนี้ + +| Model | Model ID | Endpoint | AI SDK Package | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +[รหัสโมเดล](/docs/config/#models) ในการกำหนดค่า OpenCode ของคุณใช้รูปแบบ `opencode-go/` ตัวอย่างเช่น สำหรับ Kimi K2.5 คุณจะใช้ `opencode-go/kimi-k2.5` ในการกำหนดค่าของคุณ + +--- + +## ความเป็นส่วนตัว + +แผนนี้ออกแบบมาสำหรับผู้ใช้ระดับนานาชาติเป็นหลัก โดยมีโมเดลโฮสต์อยู่ในสหรัฐอเมริกา สหภาพยุโรป และสิงคโปร์ เพื่อการเข้าถึงที่เสถียรทั่วโลก + +ติดต่อเรา หากคุณมีข้อสงสัยใดๆ + +--- + +## เป้าหมาย + +เราสร้าง OpenCode Go เพื่อ: + +1. ทำให้การเขียนโค้ดด้วย AI **เข้าถึงได้** สำหรับผู้คนมากขึ้นด้วยการสมัครสมาชิกราคาประหยัด +2. ให้การเข้าถึงโมเดลการเขียนโค้ดแบบเปิดที่ดีที่สุดอย่าง **น่าเชื่อถือ** +3. คัดสรรโมเดลที่ผ่านการ **ทดสอบและวัดประสิทธิภาพ** สำหรับการใช้งานตัวแทน (Agent) เขียนโค้ด +4. **ไม่มีการผูกมัด** โดยอนุญาตให้คุณใช้ผู้ให้บริการรายอื่นกับ OpenCode ได้เช่นกัน diff --git a/packages/web/src/content/docs/th/keybinds.mdx b/packages/web/src/content/docs/th/keybinds.mdx index 2fbcd02a6e..8cc7586e5f 100644 --- a/packages/web/src/content/docs/th/keybinds.mdx +++ b/packages/web/src/content/docs/th/keybinds.mdx @@ -3,11 +3,11 @@ title: ปุ่มลัด description: ปรับแต่งปุ่มลัดของคุณ --- -OpenCode มีรายการปุ่มลัดที่คุณปรับแต่งได้ผ่านการกำหนดค่า OpenCode +OpenCode มีรายการปุ่มลัดที่คุณปรับแต่งได้ผ่าน `tui.json` -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -117,11 +117,11 @@ OpenCode ใช้ปุ่ม `leader` สำหรับการเชื่ ## ปิดการใช้งานการผูกปุ่ม -คุณสามารถปิดการใช้งานการผูกปุ่มได้โดยการเพิ่มคีย์ลงในการกำหนดค่าของคุณด้วยค่า "none" +คุณสามารถปิดการใช้งานการผูกปุ่มได้โดยการเพิ่มคีย์ลงใน `tui.json` ด้วยค่า "none" -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/th/lsp.mdx b/packages/web/src/content/docs/th/lsp.mdx index 0e5e28c4a6..91d3f479fb 100644 --- a/packages/web/src/content/docs/th/lsp.mdx +++ b/packages/web/src/content/docs/th/lsp.mdx @@ -11,40 +11,41 @@ OpenCode ทำงานร่วมกับ Language Server Protocol (LSP) เ OpenCode มาพร้อมกับเซิร์ฟเวอร์ LSP ในตัวหลายตัวสำหรับภาษายอดนิยม: -| LSP เซิร์ฟเวอร์ | ส่วนขยาย | ความต้องการ | -| -------------------- | ------------------------------------------------------------------- | ------------------------------------------------------- | -| astro | .astro | ติดตั้งอัตโนมัติสำหรับโปรเจ็กต์ Astro | -| bash | .sh, .bash, .zsh, .ksh | ติดตั้ง bash-Language-Server โดยอัตโนมัติ | -| clang | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | ติดตั้งอัตโนมัติสำหรับโครงการ C/C++ | -| csharp | .cs | `.NET SDK` ติดตั้งแล้ว | -| clojure-lsp | .clj, .cljs, .cljc, .edn | `clojure-lsp` คำสั่งใช้ได้ | -| dart | .dart | `dart` คำสั่งใช้ได้ | -| deno | .ts, .tsx, .js, .jsx, .mjs | มีคำสั่ง `deno` (ตรวจจับอัตโนมัติ deno.json/deno.jsonc) | -| elixir-ls | .ex, .exs | `elixir` คำสั่งใช้ได้ | -| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | `eslint` การพึ่งพาในโครงการ | -| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` ติดตั้งแล้ว | -| gleam | .gleam | `gleam` คำสั่งใช้ได้ | -| gopls | .go | `go` คำสั่งใช้ได้ | -| haskell | .hs, .lhs | `haskell-language-server-wrapper` คำสั่งใช้ได้ | -| jdtls | .java | `Java SDK (version 21+)` ติดตั้งแล้ว | -| kotlin-ls | .kt, .kts | ติดตั้งอัตโนมัติสำหรับโปรเจ็กต์ Kotlin | -| lua-ls | .lua | ติดตั้งอัตโนมัติสำหรับโปรเจ็กต์ Lua | -| nix | .nix | `nixd` คำสั่งใช้ได้ | -| ocaml-lsp | .ml, .mli | `ocamllsp` คำสั่งใช้ได้ | -| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | `oxlint` การพึ่งพาในโครงการ | -| php intelephense.php | .php | ติดตั้งอัตโนมัติสำหรับโครงการ PHP | -| prisma | .prisma | `prisma` คำสั่งใช้ได้ | -| pyright | .py, .pyi | `pyright` ติดตั้งการพึ่งพาแล้ว | -| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | มีคำสั่ง `ruby` และ `gem` | -| rust | .rs | `rust-analyzer` คำสั่งใช้ได้ | -| sourcekit-lsp | .swift, .objc, .objcpp | ติดตั้ง `swift` (`xcode` บน macOS) | -| svelte | .svelte | ติดตั้งอัตโนมัติสำหรับโครงการ Svelte | -| terraform | .tf, .tfvars | ติดตั้งอัตโนมัติจากรุ่น GitHub | -| tinymist | .typ, .typst | ติดตั้งอัตโนมัติจากรุ่น GitHub | -| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` การพึ่งพาในโครงการ | -| vue | .vue | ติดตั้งอัตโนมัติสำหรับโปรเจ็กต์ Vue | -| yaml-ls | .yaml, .yml | ติดตั้งเซิร์ฟเวอร์ภาษา Red Hat yaml โดยอัตโนมัติ | -| zls | .zig, .zon | `zig` คำสั่งใช้ได้ | +| LSP เซิร์ฟเวอร์ | ส่วนขยาย | ความต้องการ | +| ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------- | +| astro | .astro | ติดตั้งอัตโนมัติสำหรับโปรเจ็กต์ Astro | +| bash | .sh, .bash, .zsh, .ksh | ติดตั้ง bash-Language-Server โดยอัตโนมัติ | +| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | ติดตั้งอัตโนมัติสำหรับโครงการ C/C++ | +| csharp | .cs | `.NET SDK` ติดตั้งแล้ว | +| clojure-lsp | .clj, .cljs, .cljc, .edn | `clojure-lsp` คำสั่งใช้ได้ | +| dart | .dart | `dart` คำสั่งใช้ได้ | +| deno | .ts, .tsx, .js, .jsx, .mjs | มีคำสั่ง `deno` (ตรวจจับอัตโนมัติ deno.json/deno.jsonc) | +| elixir-ls | .ex, .exs | `elixir` คำสั่งใช้ได้ | +| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | `eslint` การพึ่งพาในโครงการ | +| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` ติดตั้งแล้ว | +| gleam | .gleam | `gleam` คำสั่งใช้ได้ | +| gopls | .go | `go` คำสั่งใช้ได้ | +| hls | .hs, .lhs | `haskell-language-server-wrapper` คำสั่งใช้ได้ | +| jdtls | .java | `Java SDK (version 21+)` ติดตั้งแล้ว | +| julials | .jl | ติดตั้ง `julia` และ `LanguageServer.jl` แล้ว | +| kotlin-ls | .kt, .kts | ติดตั้งอัตโนมัติสำหรับโปรเจ็กต์ Kotlin | +| lua-ls | .lua | ติดตั้งอัตโนมัติสำหรับโปรเจ็กต์ Lua | +| nixd | .nix | `nixd` คำสั่งใช้ได้ | +| ocaml-lsp | .ml, .mli | `ocamllsp` คำสั่งใช้ได้ | +| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | `oxlint` การพึ่งพาในโครงการ | +| php intelephense | .php | ติดตั้งอัตโนมัติสำหรับโครงการ PHP | +| prisma | .prisma | `prisma` คำสั่งใช้ได้ | +| pyright | .py, .pyi | `pyright` ติดตั้งการพึ่งพาแล้ว | +| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | มีคำสั่ง `ruby` และ `gem` | +| rust | .rs | `rust-analyzer` คำสั่งใช้ได้ | +| sourcekit-lsp | .swift, .objc, .objcpp | ติดตั้ง `swift` (`xcode` บน macOS) | +| svelte | .svelte | ติดตั้งอัตโนมัติสำหรับโครงการ Svelte | +| terraform | .tf, .tfvars | ติดตั้งอัตโนมัติจากรุ่น GitHub | +| tinymist | .typ, .typc | ติดตั้งอัตโนมัติจากรุ่น GitHub | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` การพึ่งพาในโครงการ | +| vue | .vue | ติดตั้งอัตโนมัติสำหรับโปรเจ็กต์ Vue | +| yaml-ls | .yaml, .yml | ติดตั้งเซิร์ฟเวอร์ภาษา Red Hat yaml โดยอัตโนมัติ | +| zls | .zig, .zon | `zig` คำสั่งใช้ได้ | เซิร์ฟเวอร์ LSP จะถูกเปิดใช้งานโดยอัตโนมัติเมื่อตรวจพบนามสกุลไฟล์ใดนามสกุลหนึ่งข้างต้นและเป็นไปตามข้อกำหนด diff --git a/packages/web/src/content/docs/th/plugins.mdx b/packages/web/src/content/docs/th/plugins.mdx index a2d74ceb9c..e672715a4e 100644 --- a/packages/web/src/content/docs/th/plugins.mdx +++ b/packages/web/src/content/docs/th/plugins.mdx @@ -308,6 +308,10 @@ export const CustomToolsPlugin: Plugin = async (ctx) => { เครื่องมือที่คุณกำหนดเองจะพร้อมใช้งานสำหรับ opencode ควบคู่ไปกับเครื่องมือในตัว +:::note +หากเครื่องมือปลั๊กอินใช้ชื่อเดียวกับเครื่องมือในตัว เครื่องมือปลั๊กอินจะมีความสำคัญเหนือกว่า +::: + --- ### การบันทึก diff --git a/packages/web/src/content/docs/th/providers.mdx b/packages/web/src/content/docs/th/providers.mdx index e9fbb351d7..122ade4277 100644 --- a/packages/web/src/content/docs/th/providers.mdx +++ b/packages/web/src/content/docs/th/providers.mdx @@ -84,6 +84,37 @@ OpenCode Zen คือรายชื่อโมเดลที่จัดท --- +## OpenCode Go + +OpenCode Go คือแผนการสมัครสมาชิกราคาประหยัดที่ให้การเข้าถึงโมเดลการเขียนโค้ดแบบเปิดยอดนิยมที่เชื่อถือได้ ซึ่งจัดเตรียมโดยทีมงาน OpenCode ที่ได้รับการทดสอบและตรวจสอบแล้วว่าทำงานได้ดีกับ OpenCode + +1. เรียกใช้คำสั่ง `/connect` ใน TUI เลือก `OpenCode Go` และไปที่ [opencode.ai/auth](https://opencode.ai/zen) + + ```txt + /connect + ``` + +2. ลงชื่อเข้าใช้ เพิ่มรายละเอียดการเรียกเก็บเงินของคุณ และคัดลอกรหัส API ของคุณ + +3. วางคีย์ API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. เรียกใช้ `/models` ใน TUI เพื่อดูรายการรุ่นที่เราแนะนำ + + ```txt + /models + ``` + +มันทำงานเหมือนกับผู้ให้บริการรายอื่นใน OpenCode และเป็นทางเลือกในการใช้งานโดยสมบูรณ์ + +--- + ## ไดเรกทอรี มาดูรายละเอียดผู้ให้บริการบางรายกัน หากคุณต้องการเพิ่มผู้ให้บริการให้กับ @@ -1354,6 +1385,583 @@ OpenCode Zen คือรายการโมเดลที่ได้รั └ enter ``` +4. รันคำสั่ง `/models` เพื่อเลือกโมเดลเช่น _Qwen 3 Coder 480B_ + + ```txt + /models + ``` + +--- + +### OpenRouter + +1. ไปที่ [OpenRouter dashboard](https://openrouter.ai/settings/keys) คลิก **Create API Key** และคัดลอกคีย์ + +2. เรียกใช้คำสั่ง `/connect` และค้นหา OpenRouter + + ```txt + /connect + ``` + +3. ป้อนคีย์ API สำหรับผู้ให้บริการ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. โมเดล OpenRouter จำนวนมากถูกโหลดไว้ล่วงหน้าตามค่าเริ่มต้น รันคำสั่ง `/models` เพื่อเลือกโมเดลที่คุณต้องการ + + ```txt + /models + ``` + + คุณยังสามารถเพิ่มโมเดลเพิ่มเติมผ่านการกำหนดค่า opencode ของคุณได้ + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +5. คุณยังสามารถปรับแต่งได้ผ่านการกำหนดค่า opencode ของคุณ นี่คือตัวอย่างการระบุผู้ให้บริการ + + ```json title="opencode.json" + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "openrouter": { + "models": { + "moonshotai/kimi-k2": { + "options": { + "provider": { + "order": ["baseten"], + "allow_fallbacks": false + } + } + } + } + } + } + } + ``` + +--- + +### SAP AI Core + +SAP AI Core ให้การเข้าถึงโมเดลมากกว่า 40 รุ่นจาก OpenAI, Anthropic, Google, Amazon, Meta, Mistral และ AI21 ผ่านแพลตฟอร์มเดียว + +1. ไปที่ [SAP BTP Cockpit](https://account.hana.ondemand.com/) ของคุณ ไปที่อินสแตนซ์บริการ SAP AI Core และสร้างคีย์บริการ + + :::tip + คีย์บริการคือวัตถุ JSON ที่มี `clientid`, `clientsecret`, `url` และ `serviceurls.AI_API_URL` คุณสามารถค้นหาอินสแตนซ์ AI Core ของคุณได้ภายใต้ **Services** > **Instances and Subscriptions** ใน BTP Cockpit + ::: + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **SAP AI Core** + + ```txt + /connect + ``` + +3. ป้อน JSON คีย์บริการของคุณ + + ```txt + ┌ Service key + │ + │ + └ enter + ``` + + หรือตั้งค่าตัวแปรสภาพแวดล้อม `AICORE_SERVICE_KEY`: + + ```bash + AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' opencode + ``` + + หรือเพิ่มลงในโปรไฟล์ทุบตีของคุณ: + + ```bash title="~/.bash_profile" + export AICORE_SERVICE_KEY='{"clientid":"...","clientsecret":"...","url":"...","serviceurls":{"AI_API_URL":"..."}}' + ``` + +4. เลือกตั้งค่ารหัสการปรับใช้และกลุ่มทรัพยากร: + + ```bash + AICORE_DEPLOYMENT_ID=your-deployment-id AICORE_RESOURCE_GROUP=your-resource-group opencode + ``` + + :::note + การตั้งค่าเหล่านี้เป็นทางเลือกและควรกำหนดค่าตามการตั้งค่า SAP AI Core ของคุณ + ::: + +5. รันคำสั่ง `/models` เพื่อเลือกจาก 40+ รุ่นที่มีอยู่ + + ```txt + /models + ``` + +--- + +### STACKIT + +STACKIT AI Model Serving มอบสภาพแวดล้อมการโฮสต์ที่มีการจัดการเต็มรูปแบบสำหรับโมเดล AI โดยเน้นที่ LLM เช่น Llama, Mistral และ Qwen โดยมีอธิปไตยของข้อมูลสูงสุดบนโครงสร้างพื้นฐานยุโรป + +1. ไปที่ [STACKIT Portal](https://portal.stackit.cloud) ไปที่ **AI Model Serving** และสร้างโทเค็นการตรวจสอบสิทธิ์สำหรับโครงการของคุณ + + :::tip + คุณต้องมีบัญชีลูกค้า STACKIT บัญชีผู้ใช้ และโครงการก่อนสร้างโทเค็นการตรวจสอบสิทธิ์ + ::: + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **STACKIT** + + ```txt + /connect + ``` + +3. ป้อนโทเค็นการตรวจสอบสิทธิ์ STACKIT AI Model Serving ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกจากโมเดลที่มีอยู่ เช่น _Qwen3-VL 235B_ หรือ _Llama 3.3 70B_ + + ```txt + /models + ``` + +--- + +### OVHcloud AI Endpoints + +1. ไปที่ [OVHcloud panel](https://ovh.com/manager) ไปที่ส่วน `Public Cloud`, `AI & Machine Learning` > `AI Endpoints` และในแท็บ `API Keys` ให้คลิก **Create a new API key** + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **OVHcloud AI Endpoints** + + ```txt + /connect + ``` + +3. ป้อนคีย์ API OVHcloud AI Endpoints ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดลเช่น _gpt-oss-120b_ + + ```txt + /models + ``` + +--- + +### Scaleway + +วิธีใช้ [Scaleway Generative APIs](https://www.scaleway.com/en/docs/generative-apis/) กับ Opencode: + +1. ไปที่ [Scaleway Console IAM settings](https://console.scaleway.com/iam/api-keys) เพื่อสร้างคีย์ API ใหม่ + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **Scaleway** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Scaleway API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดลเช่น _devstral-2-123b-instruct-2512_ หรือ _gpt-oss-120b_ + + ```txt + /models + ``` + +--- + +### Together AI + +1. ไปที่ [Together AI console](https://api.together.ai) สร้างบัญชี และคลิก **Add Key** + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **Together AI** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Together AI API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดลเช่น _Kimi K2 Instruct_ + + ```txt + /models + ``` + +--- + +### Venice AI + +1. ไปที่ [Venice AI console](https://venice.ai) สร้างบัญชี และสร้างคีย์ API + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **Venice AI** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Venice AI API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดลเช่น _Llama 3.3 70B_ + + ```txt + /models + ``` + +--- + +### Vercel AI Gateway + +Vercel AI Gateway ช่วยให้คุณเข้าถึงโมเดลจาก OpenAI, Anthropic, Google, xAI และอื่นๆ อีกมากมายผ่านจุดสิ้นสุดแบบรวม โมเดลถูกนำเสนอในราคาปลีกโดยไม่มีการบวกเพิ่ม + +1. ไปที่ [Vercel dashboard](https://vercel.com/) ไปที่แท็บ **AI Gateway** และคลิก **API keys** เพื่อสร้างคีย์ API ใหม่ + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **Vercel AI Gateway** + + ```txt + /connect + ``` + +3. ป้อนคีย์ Vercel AI Gateway API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกรุ่น + + ```txt + /models + ``` + +คุณยังสามารถปรับแต่งโมเดลผ่านการกำหนดค่า opencode ของคุณได้ นี่คือตัวอย่างการระบุลำดับการกำหนดเส้นทางผู้ให้บริการ + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "vercel": { + "models": { + "anthropic/claude-sonnet-4": { + "options": { + "order": ["anthropic", "vertex"] + } + } + } + } + } +} +``` + +ตัวเลือกการกำหนดเส้นทางที่มีประโยชน์บางประการ: + +| ตัวเลือก | คำอธิบาย | +| ------------------- | ---------------------------------------------------------- | +| `order` | ลำดับผู้ให้บริการที่จะลอง | +| `only` | จำกัดเฉพาะผู้ให้บริการที่ระบุ | +| `zeroDataRetention` | ใช้เฉพาะผู้ให้บริการที่มีนโยบายการเก็บรักษาข้อมูลเป็นศูนย์ | + +--- + +### xAI + +1. ไปที่ [xAI console](https://console.x.ai/) สร้างบัญชี และสร้างคีย์ API + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **xAI** + + ```txt + /connect + ``` + +3. ป้อนคีย์ xAI API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดลเช่น _Grok Beta_ + + ```txt + /models + ``` + +--- + +### Z.AI + +1. ไปที่ [Z.AI API console](https://z.ai/manage-apikey/apikey-list) สร้างบัญชี และคลิก **Create a new API key** + +2. เรียกใช้คำสั่ง `/connect` และค้นหา **Z.AI** + + ```txt + /connect + ``` + + หากคุณสมัครรับ **GLM Coding Plan** ให้เลือก **Z.AI Coding Plan** + +3. ป้อนคีย์ Z.AI API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. รันคำสั่ง `/models` เพื่อเลือกโมเดลเช่น _GLM-4.7_ + + ```txt + /models + ``` + +--- + +### ZenMux + +1. ไปที่ [ZenMux dashboard](https://zenmux.ai/settings/keys) คลิก **Create API Key** และคัดลอกคีย์ + +2. เรียกใช้คำสั่ง `/connect` และค้นหา ZenMux + + ```txt + /connect + ``` + +3. ป้อนคีย์ API สำหรับผู้ให้บริการ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. โมเดล ZenMux จำนวนมากถูกโหลดไว้ล่วงหน้าตามค่าเริ่มต้น รันคำสั่ง `/models` เพื่อเลือกโมเดลที่คุณต้องการ + + ```txt + /models + ``` + + คุณยังสามารถเพิ่มโมเดลเพิ่มเติมผ่านการกำหนดค่า opencode ของคุณได้ + + ```json title="opencode.json" {6} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "zenmux": { + "models": { + "somecoolnewmodel": {} + } + } + } + } + ``` + +--- + +## ผู้ให้บริการที่กำหนดเอง + +หากต้องการเพิ่มผู้ให้บริการที่ **เข้ากันได้กับ OpenAI** ใดๆ ที่ไม่มีรายชื่ออยู่ในคำสั่ง `/connect`: + +:::tip +คุณสามารถใช้ผู้ให้บริการที่เข้ากันได้กับ OpenAI กับ opencode ได้ ผู้ให้บริการ AI สมัยใหม่ส่วนใหญ่เสนอ API ที่เข้ากันได้กับ OpenAI +::: + +1. เรียกใช้คำสั่ง `/connect` และเลื่อนลงไปที่ **Other** + + ```bash + $ /connect + + ┌ Add credential + │ + ◆ Select provider + │ ... + │ ● Other + └ + ``` + +2. ป้อน ID เฉพาะสำหรับผู้ให้บริการ + + ```bash + $ /connect + + ┌ Add credential + │ + ◇ Enter provider id + │ myprovider + └ + ``` + + :::note + เลือก ID ที่น่าจดจำ คุณจะใช้ ID นี้ในไฟล์กำหนดค่าของคุณ + ::: + +3. ป้อนคีย์ API สำหรับผู้ให้บริการ + + ```bash + $ /connect + + ┌ Add credential + │ + ▲ This only stores a credential for myprovider - you will need to configure it in opencode.json, check the docs for examples. + │ + ◇ Enter your API key + │ sk-... + └ + ``` + +4. สร้างหรืออัปเดตไฟล์ `opencode.json` ของคุณในไดเร็กทอรีโครงการของคุณ: + + ```json title="opencode.json" ""myprovider"" {5-15} + { + "$schema": "https://opencode.ai/config.json", + "provider": { + "myprovider": { + "npm": "@ai-sdk/openai-compatible", + "name": "My AI ProviderDisplay Name", + "options": { + "baseURL": "https://api.myprovider.com/v1" + }, + "models": { + "my-model-name": { + "name": "My Model Display Name" + } + } + } + } + } + ``` + + นี่คือตัวเลือกการกำหนดค่า: + - **npm**: แพ็คเกจ AI SDK ที่จะใช้ `@ai-sdk/openai-compatible` สำหรับผู้ให้บริการที่เข้ากันได้กับ OpenAI + - **name**: ชื่อที่แสดงใน UI + - **models**: โมเดลที่มีจำหน่าย + - **options.baseURL**: URL จุดสิ้นสุด API + - **options.apiKey**: ตั้งค่าคีย์ API ทางเลือก หากไม่ได้ใช้การรับรองความถูกต้อง + - **options.headers**: ตั้งค่าส่วนหัวที่กำหนดเองได้ตามต้องการ + + ข้อมูลเพิ่มเติมเกี่ยวกับตัวเลือกขั้นสูงในตัวอย่างด้านล่าง + +5. รันคำสั่ง `/models` และผู้ให้บริการและโมเดลที่คุณกำหนดเองจะปรากฏในรายการตัวเลือก + +--- + +##### ตัวอย่าง + +นี่คือตัวอย่างการตั้งค่าตัวเลือก `apiKey`, `headers` และรุ่น `limit` + +```json title="opencode.json" {9,11,17-20} +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "myprovider": { + "npm": "@ai-sdk/openai-compatible", + "name": "My AI ProviderDisplay Name", + "options": { + "baseURL": "https://api.myprovider.com/v1", + "apiKey": "{env:ANTHROPIC_API_KEY}", + "headers": { + "Authorization": "Bearer custom-token" + } + }, + "models": { + "my-model-name": { + "name": "My Model Display Name", + "limit": { + "context": 200000, + "output": 65536 + } + } + } + } + } +} +``` + +รายละเอียดการกำหนดค่า: + +- **apiKey**: ตั้งค่าโดยใช้ไวยากรณ์ตัวแปร `env` [เรียนรู้เพิ่มเติม](/docs/config#env-vars) +- **headers**: ส่วนหัวที่กำหนดเองที่ส่งไปกับแต่ละคำขอ +- **limit.context**: โทเค็นอินพุตสูงสุดที่โมเดลยอมรับ +- **limit.output**: โทเค็นสูงสุดที่โมเดลสามารถสร้างได้ + +ฟิลด์ `limit` ช่วยให้ OpenCode เข้าใจว่าคุณมีบริบทเหลืออยู่เท่าใด ผู้ให้บริการมาตรฐานจะดึงข้อมูลเหล่านี้จาก models.dev โดยอัตโนมัติ + +--- + +## การแก้ไขปัญหา + +หากคุณประสบปัญหาในการกำหนดค่าผู้ให้บริการ ให้ตรวจสอบสิ่งต่อไปนี้: + +1. **ตรวจสอบการตั้งค่าการรับรองความถูกต้อง**: รัน `opencode auth list` เพื่อดูว่ามีการเพิ่มข้อมูลรับรอง + สำหรับผู้ให้บริการในการกำหนดค่าของคุณหรือไม่ + + สิ่งนี้ใช้ไม่ได้กับผู้ให้บริการเช่น Amazon Bedrock ซึ่งอาศัยตัวแปรสภาพแวดล้อมสำหรับการตรวจสอบสิทธิ์ + +2. สำหรับผู้ให้บริการที่กำหนดเอง ให้ตรวจสอบการกำหนดค่า opencode และ: + - ตรวจสอบให้แน่ใจว่า ID ผู้ให้บริการที่ใช้ในคำสั่ง `/connect` ตรงกับ ID ในการกำหนดค่า opencode ของคุณ + - ใช้แพ็คเกจ npm ที่ถูกต้องสำหรับผู้ให้บริการ ตัวอย่างเช่น ใช้ `@ai-sdk/cerebras` สำหรับ Cerebras และสำหรับผู้ให้บริการอื่นๆ ที่เข้ากันได้กับ OpenAI ให้ใช้ `@ai-sdk/openai-compatible` + - ตรวจสอบว่าใช้จุดสิ้นสุด API ที่ถูกต้องในฟิลด์ `options.baseURL` + +3. ป้อนคีย์ OpenCode API ของคุณ + + ```txt + ┌ API key + │ + │ + └ enter + ``` + 4. รันคำสั่ง `/models` เพื่อเลือกรุ่นเช่น _Qwen 3 Coder 480B_ ```txt diff --git a/packages/web/src/content/docs/th/sdk.mdx b/packages/web/src/content/docs/th/sdk.mdx index b592c1a4e4..3454b57667 100644 --- a/packages/web/src/content/docs/th/sdk.mdx +++ b/packages/web/src/content/docs/th/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## ผลลัพธ์แบบมีโครงสร้าง + +คุณสามารถร้องขอผลลัพธ์ JSON แบบมีโครงสร้างจากโมเดลได้โดยระบุ `format` ด้วย JSON schema โมเดลจะใช้เครื่องมือ `StructuredOutput` เพื่อส่งคืน JSON ที่ผ่านการตรวจสอบความถูกต้องซึ่งตรงกับสคีมาของคุณ + +### การใช้งานพื้นฐาน + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Research Anthropic and provide company info" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Company name" }, + founded: { type: "number", description: "Year founded" }, + products: { + type: "array", + items: { type: "string" }, + description: "Main products", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Access the structured output +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### ประเภทรูปแบบผลลัพธ์ + +| ประเภท | คำอธิบาย | +| ------------- | ----------------------------------------------------------------- | +| `text` | ค่าเริ่มต้น การตอบสนองข้อความมาตรฐาน (ไม่มีผลลัพธ์แบบมีโครงสร้าง) | +| `json_schema` | ส่งคืน JSON ที่ผ่านการตรวจสอบความถูกต้องซึ่งตรงกับสคีมาที่ระบุ | + +### รูปแบบ JSON Schema + +เมื่อใช้ `type: 'json_schema'` ให้ระบุ: + +| ฟิลด์ | Type | คำอธิบาย | +| ------------ | --------------- | --------------------------------------------------------------------- | +| `type` | `'json_schema'` | จำเป็น ระบุโหมด JSON schema | +| `schema` | `object` | จำเป็น วัตถุ JSON Schema ที่กำหนดโครงสร้างผลลัพธ์ | +| `retryCount` | `number` | ไม่จำเป็น จำนวนการลองใหม่สำหรับการตรวจสอบความถูกต้อง (ค่าเริ่มต้น: 2) | + +### การจัดการข้อผิดพลาด + +หากโมเดลล้มเหลวในการสร้างผลลัพธ์แบบมีโครงสร้างที่ถูกต้องหลังจากลองใหม่ครบทุกครั้ง การตอบสนองจะรวม `StructuredOutputError`: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Failed to produce structured output:", result.data.info.error.message) + console.error("Attempts:", result.data.info.error.retries) +} +``` + +### แนวปฏิบัติที่ดีที่สุด + +1. **ระบุคำอธิบายที่ชัดเจน** ในคุณสมบัติสคีมาของคุณเพื่อช่วยให้โมเดลเข้าใจว่าข้อมูลใดที่ต้องดึงออกมา +2. **ใช้ `required`** เพื่อระบุฟิลด์ที่ต้องมี +3. **รักษาสคีมาให้โฟกัส** - สคีมาที่ซ้อนกันซับซ้อนอาจยากสำหรับโมเดลในการกรอกให้ถูกต้อง +4. **ตั้งค่า `retryCount` ที่เหมาะสม** - เพิ่มสำหรับสคีมาที่ซับซ้อน ลดลงสำหรับสคีมาที่เรียบง่าย + +--- + ## API SDK เปิดเผย API ของเซิร์ฟเวอร์ทั้งหมดผ่านไคลเอ็นต์ประเภทที่ปลอดภัย @@ -226,27 +298,27 @@ const { providers, default: defaults } = await client.config.providers() ### เซสชัน -| Method | คำอธิบาย | หมายเหตุ | -| ---------------------------------------------------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | แสดงรายการเซสชัน | ส่งคืน เซสชัน[] | -| `session.get({ path })` | รับเซสชัน | ส่งคืน เซสชัน | -| `session.children({ path })` | แสดงรายการเซสชันย่อย | ส่งคืน เซสชัน[] | -| `session.create({ body })` | สร้างเซสชัน | ส่งคืน เซสชัน | -| `session.delete({ path })` | ลบเซสชัน | ส่งคืน `boolean` | -| `session.update({ path, body })` | อัปเดตคุณสมบัติเซสชัน | ส่งคืน เซสชัน | -| `session.init({ path, body })` | วิเคราะห์แอปและสร้าง `AGENTS.md` | ส่งคืน `boolean` | -| `session.abort({ path })` | ยกเลิกเซสชันที่ทำงานอยู่ | ส่งคืน `boolean` | -| `session.share({ path })` | แบ่งปันเซสชั่น | ส่งคืน เซสชัน | -| `session.unshare({ path })` | เลิกแชร์เซสชัน | ส่งคืน เซสชัน | -| `session.summarize({ path, body })` | สรุปเซสชัน | ส่งคืน `boolean` | -| `session.messages({ path })` | แสดงรายการข้อความในเซสชัน | ส่งคืน `{ info: `ข้อความ`, parts: `ส่วน[]`}[]` | -| `session.message({ path })` | รับรายละเอียดข้อความ | ส่งคืน `{ info: `ข้อความ`, parts: `ส่วน[]`}` | -| `session.prompt({ path, body })` | ส่งข้อความแจ้ง | `body.noReply: true` ส่งคืน UserMessage (บริบทเท่านั้น) ค่าเริ่มต้นส่งคืน AssistantMessage พร้อมการตอบสนองของ AI | -| `session.command({ path, body })` | ส่งคำสั่งไปยังเซสชั่น | ส่งคืน `{ info: `AssistantMessage`, parts: `ส่วน[]`}` | -| `session.shell({ path, body })` | รันคำสั่ง shell | ส่งคืน AssistantMessage | -| `session.revert({ path, body })` | คืนค่าข้อความ | ส่งคืน เซสชัน | -| `session.unrevert({ path })` | คืนค่าข้อความที่เปลี่ยนกลับ | ส่งคืน เซสชัน | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | ตอบสนองต่อการร้องขอการอนุญาต | ส่งคืน `boolean` | +| Method | คำอธิบาย | หมายเหตุ | +| ---------------------------------------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | แสดงรายการเซสชัน | ส่งคืน เซสชัน[] | +| `session.get({ path })` | รับเซสชัน | ส่งคืน เซสชัน | +| `session.children({ path })` | แสดงรายการเซสชันย่อย | ส่งคืน เซสชัน[] | +| `session.create({ body })` | สร้างเซสชัน | ส่งคืน เซสชัน | +| `session.delete({ path })` | ลบเซสชัน | ส่งคืน `boolean` | +| `session.update({ path, body })` | อัปเดตคุณสมบัติเซสชัน | ส่งคืน เซสชัน | +| `session.init({ path, body })` | วิเคราะห์แอปและสร้าง `AGENTS.md` | ส่งคืน `boolean` | +| `session.abort({ path })` | ยกเลิกเซสชันที่ทำงานอยู่ | ส่งคืน `boolean` | +| `session.share({ path })` | แบ่งปันเซสชั่น | ส่งคืน เซสชัน | +| `session.unshare({ path })` | เลิกแชร์เซสชัน | ส่งคืน เซสชัน | +| `session.summarize({ path, body })` | สรุปเซสชัน | ส่งคืน `boolean` | +| `session.messages({ path })` | แสดงรายการข้อความในเซสชัน | ส่งคืน `{ info: `ข้อความ`, parts: `ส่วน[]`}[]` | +| `session.message({ path })` | รับรายละเอียดข้อความ | ส่งคืน `{ info: `ข้อความ`, parts: `ส่วน[]`}` | +| `session.prompt({ path, body })` | ส่งข้อความแจ้ง | `body.noReply: true` ส่งคืน UserMessage (บริบทเท่านั้น) ค่าเริ่มต้นส่งคืน AssistantMessage พร้อมการตอบสนองของ AI รองรับ `body.outputFormat` สำหรับ [ผลลัพธ์แบบมีโครงสร้าง](#ผลลัพธ์แบบมีโครงสร้าง) | +| `session.command({ path, body })` | ส่งคำสั่งไปยังเซสชั่น | ส่งคืน `{ info: `AssistantMessage`, parts: `ส่วน[]`}` | +| `session.shell({ path, body })` | รันคำสั่ง shell | ส่งคืน AssistantMessage | +| `session.revert({ path, body })` | คืนค่าข้อความ | ส่งคืน เซสชัน | +| `session.unrevert({ path })` | คืนค่าข้อความที่เปลี่ยนกลับ | ส่งคืน เซสชัน | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | ตอบสนองต่อการร้องขอการอนุญาต | ส่งคืน `boolean` | --- diff --git a/packages/web/src/content/docs/th/themes.mdx b/packages/web/src/content/docs/th/themes.mdx index 2244c3dcf1..44514148ea 100644 --- a/packages/web/src/content/docs/th/themes.mdx +++ b/packages/web/src/content/docs/th/themes.mdx @@ -61,11 +61,11 @@ OpenCode มาพร้อมกับธีมในตัวหลายธ ## การใช้ธีม -คุณสามารถเลือกธีมได้โดยเปิดการเลือกธีมขึ้นมาด้วยคำสั่ง `/theme` หรือคุณสามารถระบุได้ใน [config](/docs/config) +คุณสามารถเลือกธีมได้โดยเปิดการเลือกธีมขึ้นมาด้วยคำสั่ง `/theme` หรือคุณสามารถระบุได้ใน `tui.json` -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` diff --git a/packages/web/src/content/docs/th/tui.mdx b/packages/web/src/content/docs/th/tui.mdx index 9151462d70..2a5064b9d7 100644 --- a/packages/web/src/content/docs/th/tui.mdx +++ b/packages/web/src/content/docs/th/tui.mdx @@ -235,7 +235,7 @@ How is auth handled in @packages/functions/src/api/index.ts? แสดงรายการธีมที่มีอยู่ ```bash frame="none" -/theme +/themes ``` **ผูกปุ่ม:** `ctrl+x t` @@ -355,24 +355,34 @@ How is auth handled in @packages/functions/src/api/index.ts? ## กำหนดค่า -คุณสามารถปรับแต่งพฤติกรรม TUI ผ่านไฟล์กำหนดค่า OpenCode ของคุณได้ +คุณสามารถปรับแต่งพฤติกรรม TUI ได้ผ่าน `tui.json` (หรือ `tui.jsonc`) -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +สิ่งนี้แยกจาก `opencode.json` ซึ่งกำหนดค่าพฤติกรรมเซิร์ฟเวอร์/รันไทม์ + ### ตัวเลือก -- `scroll_acceleration` - ​​เปิดใช้งานการเร่งความเร็วการเลื่อนแบบ macOS เพื่อการเลื่อนที่ราบรื่นและเป็นธรรมชาติ เมื่อเปิดใช้งาน ความเร็วในการเลื่อนจะเพิ่มขึ้นตามท่าทางการเลื่อนอย่างรวดเร็ว และคงความแม่นยำไว้สำหรับการเคลื่อนไหวที่ช้าลง **การตั้งค่านี้มีความสำคัญมากกว่า `scroll_speed` และแทนที่เมื่อเปิดใช้งาน** -- `scroll_speed` - ​​ควบคุมความเร็วของการเลื่อน TUI เมื่อใช้คำสั่งการเลื่อน (ขั้นต่ำ: `1`) ค่าเริ่มต้นเป็น `3` **หมายเหตุ: สิ่งนี้จะถูกละเว้นหากตั้งค่า `scroll_acceleration.enabled` เป็น `true`.** +- `theme` - ตั้งค่าธีม UI ของคุณ [เรียนรู้เพิ่มเติม](/docs/themes) +- `keybinds` - ปรับแต่งแป้นพิมพ์ลัด [เรียนรู้เพิ่มเติม](/docs/keybinds) +- `scroll_acceleration.enabled` - ​​เปิดใช้งานการเร่งความเร็วการเลื่อนแบบ macOS เพื่อการเลื่อนที่ราบรื่นและเป็นธรรมชาติ เมื่อเปิดใช้งาน ความเร็วในการเลื่อนจะเพิ่มขึ้นตามท่าทางการเลื่อนอย่างรวดเร็ว และคงความแม่นยำไว้สำหรับการเคลื่อนไหวที่ช้าลง **การตั้งค่านี้มีความสำคัญมากกว่า `scroll_speed` และแทนที่เมื่อเปิดใช้งาน** +- `scroll_speed` - ​​ควบคุมความเร็วของการเลื่อน TUI เมื่อใช้คำสั่งการเลื่อน (ขั้นต่ำ: `0.001` รองรับค่าทศนิยม) ค่าเริ่มต้นเป็น `3` **หมายเหตุ: สิ่งนี้จะถูกละเว้นหากตั้งค่า `scroll_acceleration.enabled` เป็น `true`.** +- `diff_style` - ควบคุมการเรนเดอร์ diff `"auto"` ปรับให้เข้ากับความกว้างของ terminal `"stacked"` จะแสดงคอลัมน์เดียวเสมอ + +ใช้ `OPENCODE_TUI_CONFIG` เพื่อโหลดเส้นทางการกำหนดค่า TUI แบบกำหนดเอง --- diff --git a/packages/web/src/content/docs/th/zen.mdx b/packages/web/src/content/docs/th/zen.mdx index f0b39ceaaa..7b9f172756 100644 --- a/packages/web/src/content/docs/th/zen.mdx +++ b/packages/web/src/content/docs/th/zen.mdx @@ -64,31 +64,34 @@ OpenCode Zen ทำงานเหมือนกับผู้ให้บร | Model | Model ID | Endpoint | แพ็คเกจ AI SDK | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | -| GPT 5.2 | GPT-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | -| GPT 5.1 | GPT-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 Codex | gpt-5.1-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 Codex Max | gpt-5.1-codex-max | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 Codex Mini | gpt-5.1-codex-mini | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | -| GPT 5 | GPT-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | -| Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Haiku 3.5 | claude-haiku-3-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -114,41 +117,46 @@ https://opencode.ai/zen/v1/models เราสนับสนุนรูปแบบการจ่ายเงินตามการใช้งาน ด้านล่างนี้คือราคา **ต่อtokens 1M** -| Model | ป้อนข้อมูล | เอาท์พุต | แคชอ่าน | เขียนในแคช | -| --------------------------------------- | ------------ | ------------ | ------------- | ---------- | -| Big Pickle | ฟรี | ฟรี | ฟรี | - | -| MiniMax M2.1 Free | ฟรี | ฟรี | ฟรี | - | -| Miniแม็กซ์ M2.1 | $0.30 | $1.20 | $0.10 | - | -| GLM 4.7 Free | ฟรี | ฟรี | ฟรี | - | -| GLM 4.7 | $0.60 | $2.20 | $0.10 | - | -| GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 Free | ฟรี | ฟรี | ฟรี | - | -| Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | -| Kimi K2 Thinking | $0.40 | $2.50 | - | - | -| Kimi K2 | $0.40 | $2.50 | - | - | -| Qwen3 Coder 480B | $0.45 | $1.50 | - | - | -| Claude Sonnet 4.5 (tokens ≤ 200K) | $3.00 | $15.00 | $0.30 | $3.75 | -| Claude Sonnet 4.5 (> tokens 200,000) | $6.00 | $22.50 | $0.60 | $7.50 | -| Claude Sonnet 4 (tokens 200,000 tokens) | $3.00 | $15.00 | $0.30 | $3.75 | -| Claude Sonnet 4 (> tokens 200,000) | $6.00 | $22.50 | $0.60 | $7.50 | -| Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | -| Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | -| Claude Opus 4.6 (tokens ≤ 200K) | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.6 (> tokens 200,000) | $10.00 | $37.50 | $1.00 | $12.50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | -| Gemini 3 Pro (tokens ≤ 200,000) | 2.00 ดอลลาร์ | $12.00 | $0.20 | - | -| Gemini 3 Pro (tokens> 200,000) | $4.00 | $18.00 | $0.40 | - | -| Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | -| GPT 5.2 | $1.75 | $14.00 | 0.175 ดอลลาร์ | - | -| GPT 5.2 Codex | $1.75 | $14.00 | 0.175 ดอลลาร์ | - | -| GPT 5.1 | $1.07 | 8.50 ดอลลาร์ | $0.107 | - | -| GPT 5.1 Codex | $1.07 | 8.50 ดอลลาร์ | $0.107 | - | -| GPT 5.1 CodexMax | $1.25 | $10.00 | $0.125 | - | -| GPT 5.1 CodexMini | $0.25 | 2.00 ดอลลาร์ | 0.025 ดอลลาร์ | - | -| GPT 5 | $1.07 | 8.50 ดอลลาร์ | $0.107 | - | -| GPT 5 Codex | $1.07 | 8.50 ดอลลาร์ | $0.107 | - | -| GPT 5Nano | ฟรี | ฟรี | ฟรี | - | +| Model | ป้อนข้อมูล | เอาท์พุต | แคชอ่าน | เขียนในแคช | +| --------------------------------- | ---------- | -------- | ------- | ---------- | +| Big Pickle | ฟรี | ฟรี | ฟรี | - | +| MiniMax M2.5 Free | ฟรี | ฟรี | ฟรี | - | +| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | - | +| MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | +| GLM 5 | $1.00 | $3.20 | $0.20 | - | +| GLM 4.7 | $0.60 | $2.20 | $0.10 | - | +| GLM 4.6 | $0.60 | $2.20 | $0.10 | - | +| Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | +| Kimi K2 Thinking | $0.40 | $2.50 | - | - | +| Kimi K2 | $0.40 | $2.50 | - | - | +| Qwen3 Coder 480B | $0.45 | $1.50 | - | - | +| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Claude Sonnet 4.6 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.6 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | +| Claude Sonnet 4.5 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | +| Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | +| Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | +| Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | +| Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | +| Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | +| GPT 5.2 | $1.75 | $14.00 | $0.175 | - | +| GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | +| GPT 5.1 | $1.07 | $8.50 | $0.107 | - | +| GPT 5.1 Codex | $1.07 | $8.50 | $0.107 | - | +| GPT 5.1 Codex Max | $1.25 | $10.00 | $0.125 | - | +| GPT 5.1 Codex Mini | $0.25 | $2.00 | $0.025 | - | +| GPT 5 | $1.07 | $8.50 | $0.107 | - | +| GPT 5 Codex | $1.07 | $8.50 | $0.107 | - | +| GPT 5 Nano | ฟรี | ฟรี | ฟรี | - | คุณอาจสังเกตเห็น _Claude Haiku 3.5_ ในประวัติการใช้งานของคุณ นี่คือ [โมเดลราคาประหยัด](/docs/config/#models) ที่ใช้ในการสร้างชื่อเซสชันของคุณ @@ -158,9 +166,7 @@ https://opencode.ai/zen/v1/models รุ่นฟรี: -- GLM 4.7 ใช้งานได้ฟรีบน OpenCode ในระยะเวลาจำกัด ทีมงานใช้เวลานี้เพื่อรวบรวมคำติชมและปรับปรุงโมเดล -- Kimi K2.5 Free พร้อมใช้งานบน OpenCode ในระยะเวลาจำกัด ทีมงานใช้เวลานี้เพื่อรวบรวมคำติชมและปรับปรุงโมเดล -- MiniMax M2.1 Free พร้อมใช้งานบน OpenCode ในระยะเวลาจำกัด ทีมงานใช้เวลานี้เพื่อรวบรวมคำติชมและปรับปรุงโมเดล +- MiniMax M2.5 Free พร้อมใช้งานบน OpenCode ในระยะเวลาจำกัด ทีมงานใช้เวลานี้เพื่อรวบรวมคำติชมและปรับปรุงโมเดล - Big Pickle เป็นโมเดลล่องหนที่ให้บริการฟรีบน OpenCode ในระยะเวลาจำกัด ทีมงานใช้เวลานี้เพื่อรวบรวมคำติชมและปรับปรุงโมเดล Contact us if you have any questions. @@ -191,9 +197,7 @@ https://opencode.ai/zen/v1/models โมเดลทั้งหมดของเราโฮสต์ในสหรัฐอเมริกา ผู้ให้บริการของเราปฏิบัติตามนโยบายการเก็บรักษาเป็นศูนย์ และไม่ใช้ข้อมูลของคุณสำหรับการฝึกโมเดล โดยมีข้อยกเว้นต่อไปนี้: - Big Pickle: ในช่วงระยะเวลาว่าง ข้อมูลที่รวบรวมอาจนำไปใช้ในการปรับปรุงโมเดลได้ -- GLM 4.7 Free: ในช่วงระยะเวลาฟรี ข้อมูลที่รวบรวมอาจนำไปใช้ในการปรับปรุงโมเดล -- Kimi K2.5 Free: ในช่วงระยะเวลาฟรี ข้อมูลที่รวบรวมอาจนำไปใช้ในการปรับปรุงโมเดล -- MiniMax M2.1 Free: ในช่วงระยะเวลาฟรี ข้อมูลที่รวบรวมอาจนำไปใช้ในการปรับปรุงโมเดล +- MiniMax M2.5 Free: ในช่วงระยะเวลาฟรี ข้อมูลที่รวบรวมอาจนำไปใช้ในการปรับปรุงโมเดล - OpenAI API: คำขอจะถูกเก็บไว้เป็นเวลา 30 วันตาม [นโยบายข้อมูลของ OpenAI](https://platform.openai.com/docs/guides/your-data) - Anthropic API: คำขอจะถูกเก็บไว้เป็นเวลา 30 วันตาม [นโยบายข้อมูลของ Anthropic](https://docs.anthropic.com/en/docs/claude-code/data-usage) diff --git a/packages/web/src/content/docs/tr/agents.mdx b/packages/web/src/content/docs/tr/agents.mdx index 47c16abf12..1f582511be 100644 --- a/packages/web/src/content/docs/tr/agents.mdx +++ b/packages/web/src/content/docs/tr/agents.mdx @@ -21,7 +21,7 @@ opencode'da iki tür agent vardır; birincil agent'lar ve alt agent'lar. ### Birincil agent'lar -Birincil agent'lar, doğrudan etkileşim kurduğunuz ana yardımcılardır. **Sekme** tuşunu veya yapılandırılmış `switch_agent` tuş atamanızı kullanarak bunlar arasında geçiş yapabilirsiniz. Bu agent'lar ana görüşmenizi yönetir. Araç erişimi, izinler aracılığıyla yapılandırılır; örneğin, Plan kısıtlıyken Build'de tüm araçlar etkindir. +Birincil agent'lar, doğrudan etkileşim kurduğunuz ana yardımcılardır. **Sekme** tuşunu veya yapılandırılmış `switch_agent` tuş atamanızı kullanarak bunlar arasında geçiş yapabilirsiniz. Bu agent'lar ana görüşmenizi yönetir. Araç erişimi, izinler aracılığıyla yapılandırılır; örneğin, Build'de tüm araçlar etkindir ancak Plan kısıtlıdır. :::tip Bir oturum sırasında birincil agent'lar arasında geçiş yapmak için **Sekme** tuşunu kullanabilirsiniz. @@ -83,7 +83,7 @@ Kod tabanlarını keşfetmeye yönelik hızlı, salt okunur bir agent. Dosyalar --- -### Compact Kullanımı +### Compaction Kullanımı _Mod_: `primary` @@ -181,7 +181,7 @@ Agent'ları `opencode.json` yapılandırma dosyanızda yapılandırın: Ayrıca agent'ları Markdown dosyalarını kullanarak da tanımlayabilirsiniz. Bunları şuraya yerleştirin: - Global: `~/.config/opencode/agents/` -- Per-project: `.opencode/agents/` +- Proje başına: `.opencode/agents/` ```markdown title="~/.config/opencode/agents/review.md" --- @@ -342,10 +342,10 @@ Bu yol, yapılandırma dosyasının bulunduğu yere göredir. Yani bu hem global ### Model -Bu agent'ın kodu geçersiz için `model` ayarını kullanın. Farklı bölümler için optimize edilmiş farklı modelleri kullanmak için kullanışlıdır. Örneğin planlama için daha hızlı bir model, uygulama için daha yetenekli bir model. +Bu agent'ın modelini geçersiz kılmak için `model` ayarını kullanın. Farklı bölümler için optimize edilmiş farklı modelleri kullanmak için kullanışlıdır. Örneğin planlama için daha hızlı bir model, uygulama için daha yetenekli bir model. :::tip -Bir model belirtmezseniz, birincil agent'lar [model globally configured](/docs/config#models)'yi kullanırken alt agent'lar, alt agent'ı çağıran birincil agent'ın modelini kullanır. +Bir model belirtmezseniz, birincil agent'lar [küresel olarak yapılandırılmış modeli](/docs/config#models) kullanırken alt agent'lar, alt agent'ı çağıran birincil agent'ın modelini kullanır. ::: ```json title="opencode.json" @@ -358,7 +358,7 @@ Bir model belirtmezseniz, birincil agent'lar [model globally configured](/docs/c } ``` -opencode hesabınızdaki model kimliğini `provider/model-id` biçimini kullanır. Örneğin, [OpenCode Zen](/docs/zen) kullanıyorsanız, GPT 5.1 Codex için `opencode/gpt-5.1-codex` kullanırsınız. +opencode yapılandırmanızdaki model kimliği `provider/model-id` biçimini kullanır. Örneğin, [OpenCode Zen](/docs/zen) kullanıyorsanız, GPT 5.1 Codex için `opencode/gpt-5.1-codex` kullanırsınız. --- @@ -599,7 +599,7 @@ Kullanıcılar, agent'ın görev izinleri bunu reddetse bile, her zaman herhangi Agent'ın kullanıcı arayüzündeki görsel görünümünü `color` seçeneğiyle özelleştirin. Bu, agent'ın arayüzde nasıl göründüğünü etkiler. -geçerli bir onaltılık renk (ör. `#FF5733`) veya tema rengini kullanın: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. +Geçerli bir onaltılık renk (ör. `#FF5733`) veya tema rengini kullanın: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. ```json title="opencode.json" { @@ -744,627 +744,3 @@ Look for: - Dependency vulnerabilities - Configuration security issues ``` - -3. **Oturumlar arasında gezinme**: Subagent'lar kendi alt oturumlarını oluşturduğunda, aşağıdakileri kullanarak ana oturum ile tüm alt oturumlar arasında gezinebilirsiniz: - - **\+Right** (veya yapılandırılmış `session_child_cycle` tuş atamanız) ebeveyn → çocuk1 → çocuk2 → ... → ebeveyn arasında ileri doğru geçiş yapmak için - - **\+Left** (veya yapılandırılmış `session_child_cycle_reverse` tuş atamanız) ebeveyn ← çocuk1 ← çocuk2 ← ... ← ebeveyn arasında geriye doğru geçiş yapmak için - - Bu, ana görüşme ile özel subagent çalışması arasında sorunsuz bir şekilde geçiş yapmanıza olanak tanır. - ---- - -## Yapılandırma veya yapılandırma yoluyla kendinizinkini oluşturabilirsiniz. Agent'lar iki şekilde yapılandırılabilir: - ---- - -### JSON - -Agent'ları `opencode.json` yapılandırma dosyanızda yapılandırın: - -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "agent": { - "build": { - "mode": "primary", - "model": "anthropic/claude-sonnet-4-20250514", - "prompt": "{file:./prompts/build.txt}", - "tools": { - "write": true, - "edit": true, - "bash": true - } - }, - "plan": { - "mode": "primary", - "model": "anthropic/claude-haiku-4-20250514", - "tools": { - "write": false, - "edit": false, - "bash": false - } - }, - "code-reviewer": { - "description": "Reviews code for best practices and potential issues", - "mode": "subagent", - "model": "anthropic/claude-sonnet-4-20250514", - "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", - "tools": { - "write": false, - "edit": false - } - } - } -} -``` - ---- - -### Markdown - -Ayrıca agent'ları Markdown dosyalarını kullanarak da tanımlayabilirsiniz. Bunları şuraya yerleştirin: - -- Global: `~/.config/opencode/agents/` -- Per-project: `.opencode/agents/` - -```markdown title="~/.config/opencode/agents/review.md" ---- -description: Reviews code for quality and best practices -mode: subagent -model: anthropic/claude-sonnet-4-20250514 -temperature: 0.1 -tools: - write: false - edit: false - bash: false ---- - -You are in code review mode. Focus on: - -- Code quality and best practices -- Potential bugs and edge cases -- Performance implications -- Security considerations - -Provide constructive feedback without making direct changes. -``` - -Markdown dosyasının adı agent'ın adı olur. Örneğin, `review.md` bir `review` agent'ı oluşturur. - ---- - -## Seçenekler - -Bu yapılandırma seçeneklerine ayrıntılı olarak bakalım. - ---- - -### Açıklama - -Agent'ın ne yaptığına ve ne zaman kullanılacağına ilişkin kısa bir açıklama sağlamak için `description` seçeneğini kullanın. - -```json title="opencode.json" -{ - "agent": { - "review": { - "description": "Reviews code for best practices and potential issues" - } - } -} -``` - -Bu **gerekli** bir yapılandırma seçeneğidir. - ---- - -### Sıcaklık - -LLM'nin yanıtlarının rastgeleliğini ve yaratıcılığını `temperature` yapılandırmasıyla kontrol edin. - -Düşük değerler yanıtları daha odaklı ve belirleyici hale getirirken, yüksek değerler yaratıcılığı ve değişkenliği artırır. - -```json title="opencode.json" -{ - "agent": { - "plan": { - "temperature": 0.1 - }, - "creative": { - "temperature": 0.8 - } - } -} -``` - -Sıcaklık değerleri tipik olarak 0,0 ila 1,0 arasındadır: - -- **0,0-0,2**: Çok odaklı ve belirleyici yanıtlar, kod analizi ve planlama için idealdir -- **0,3-0,5**: Biraz yaratıcılık içeren dengeli yanıtlar, genel gelişim görevleri için iyi -- **0,6-1,0**: Daha yaratıcı ve çeşitli yanıtlar, beyin fırtınası ve keşif için yararlı - -```json title="opencode.json" -{ - "agent": { - "analyze": { - "temperature": 0.1, - "prompt": "{file:./prompts/analysis.txt}" - }, - "build": { - "temperature": 0.3 - }, - "brainstorm": { - "temperature": 0.7, - "prompt": "{file:./prompts/creative.txt}" - } - } -} -``` - -Sıcaklık belirtilmezse opencode modeline özgü varsayılanları kullanır; çoğu model için genellikle 0, Qwen modelleri için 0,55. - ---- - -### Maksimum adım - -Bir agent'ın yalnızca metinle yanıt vermeye zorlanmadan önce gerçekleştirebileceği maksimum agent yineleme sayısını kontrol edin. Bu, maliyetleri kontrol etmek isteyen kullanıcıların agent eylemlerine bir sınır koymasına olanak tanır. - -Bu ayarlanmazsa, model durmayı seçene veya kullanıcı oturumu kesene kadar agent yinelemeye devam edecektir. - -```json title="opencode.json" -{ - "agent": { - "quick-thinker": { - "description": "Fast reasoning with limited iterations", - "prompt": "You are a quick thinker. Solve problems with minimal steps.", - "steps": 5 - } - } -} -``` - -Sınıra ulaşıldığında, agent, işinin özeti ve önerilen kalan görevlerin bir özetiyle yanıt vermesi talimatını veren özel bir sistem prompt'u alır. - -:::caution -Eski `maxSteps` alanı kullanımdan kaldırıldı. Bunun yerine `steps` kullanın. -::: - ---- - -### Devre dışı bırakma - -Agent'ı devre dışı bırakmak için `true` olarak ayarlayın. - -```json title="opencode.json" -{ - "agent": { - "review": { - "disable": true - } - } -} -``` - ---- - -### İstem - -Bu agent için `prompt` yapılandırmasıyla özel bir sistem prompt dosyası belirtin. Prompt dosyası, agent'ın amacına özel talimatlar içermelidir. - -```json title="opencode.json" -{ - "agent": { - "review": { - "prompt": "{file:./prompts/code-review.txt}" - } - } -} -``` - -Bu yol, yapılandırma dosyasının bulunduğu yere göredir. Yani bu hem global opencode yapılandırması hem de projeye özel yapılandırma için işe yarar. - ---- - -### Model - -Bu agent'ın varsayılan modelini geçersiz kılmak için `model` ayarını kullanın. Farklı bölümler için optimize edilmiş farklı modelleri kullanmak için kullanışlıdır. Örneğin planlama için daha hızlı bir model, uygulama için daha yetenekli bir model. - -:::tip -Bir model belirtmezseniz, primary agent'lar [model globally configured](/docs/config#models)'yi kullanırken subagent'lar, subagent'ı çağıran primary agent'ın modelini kullanır. -::: - -```json title="opencode.json" -{ - "agent": { - "plan": { - "model": "anthropic/claude-haiku-4-20250514" - } - } -} -``` - -opencode hesabınızdaki model kimliğini `provider/model-id` biçimini kullanır. Örneğin, [OpenCode Zen](/docs/zen) kullanıyorsanız, GPT 5.1 Codex için `opencode/gpt-5.1-codex` kullanırsınız. - ---- - -### Araçlar - -`tools` yapılandırmasıyla bu agent'ta hangi araçların mevcut olduğunu kontrol edin. Belirli araçları `true` veya `false` olarak ayarlayarak etkinleştirebilir veya devre dışı bırakabilirsiniz. - -```json title="opencode.json" {3-6,9-12} -{ - "$schema": "https://opencode.ai/config.json", - "tools": { - "write": true, - "bash": true - }, - "agent": { - "plan": { - "tools": { - "write": false, - "bash": false - } - } - } -} -``` - -:::note -Agent'a özgü yapılandırma, genel yapılandırmayı geçersiz kılar. -::: - -Aynı anda birden fazla aracı kontrol etmek için joker karakterleri de kullanabilirsiniz. Örneğin, bir MCP sunucusundaki tüm araçları devre dışı bırakmak için: - -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "agent": { - "readonly": { - "tools": { - "mymcp_*": false, - "write": false, - "edit": false - } - } - } -} -``` - -[Araçlar hakkında daha fazla bilgi](/docs/tools). - ---- - -### İzinler - -Bir agent'ın gerçekleştirebileceği eylemleri yönetmek için izinleri yapılandırabilirsiniz. Şu anda `edit`, `bash` ve `webfetch` araçlarının izinleri şu şekilde yapılandırılabilir: - -- `"ask"` — Agent çalıştırmadan önce onay iste -- `"allow"` — Onay olmadan tüm işlemlere izin ver -- `"deny"` — Agent'ı devre dışı bırakır - -```json title="opencode.json" -{ - "$schema": "https://opencode.ai/config.json", - "permission": { - "edit": "deny" - } -} -``` - -Bu izinleri agent başına geçersiz kılabilirsiniz. - -```json title="opencode.json" {3-5,8-10} -{ - "$schema": "https://opencode.ai/config.json", - "permission": { - "edit": "deny" - }, - "agent": { - "build": { - "permission": { - "edit": "ask" - } - } - } -} -``` - -İzinleri Markdown agent'larında da ayarlayabilirsiniz. - -```markdown title="~/.config/opencode/agents/review.md" ---- -description: Code review without edits -mode: subagent -permission: - edit: deny - bash: - "*": ask - "git diff": allow - "git log*": allow - "grep *": allow - webfetch: deny ---- - -Only analyze code and suggest changes. -``` - -Belirli bash komutları için izinleri ayarlayabilirsiniz. - -```json title="opencode.json" {7} -{ - "$schema": "https://opencode.ai/config.json", - "agent": { - "build": { - "permission": { - "bash": { - "git push": "ask", - "grep *": "allow" - } - } - } - } -} -``` - -Bu küresel bir desen alabilir. - -```json title="opencode.json" {7} -{ - "$schema": "https://opencode.ai/config.json", - "agent": { - "build": { - "permission": { - "bash": { - "git *": "ask" - } - } - } - } -} -``` - -Ayrıca tüm komutların izinlerini yönetmek için `*` joker karakterini de kullanabilirsiniz. -Son eşleşen kural öncelikli olduğundan, `*` joker karakterini ilk sıraya ve belirli kuralları sonraya koyun. - -```json title="opencode.json" {8} -{ - "$schema": "https://opencode.ai/config.json", - "agent": { - "build": { - "permission": { - "bash": { - "*": "ask", - "git status *": "allow" - } - } - } - } -} -``` - -[İzinler hakkında daha fazla bilgi](/docs/permissions). - ---- - -### Mod - -Agent'ın modunu `mode` yapılandırmasıyla kontrol edin. `mode` seçeneği agent'ın nasıl kullanılabileceğini belirlemek için kullanılır. - -```json title="opencode.json" -{ - "agent": { - "review": { - "mode": "subagent" - } - } -} -``` - -`mode` seçeneği `primary`, `subagent` veya `all` olarak ayarlanabilir. `mode` belirtilmezse varsayılan olarak `all` olur. - ---- - -### Gizli - -`@` otomatik tamamlama menüsünden bir subagent'ı `hidden: true` ile gizleyin. Yalnızca diğer agent'lar tarafından Task aracı aracılığıyla programlı olarak çağrılması gereken dahili subagent'lar için kullanışlıdır. - -```json title="opencode.json" -{ - "agent": { - "internal-helper": { - "mode": "subagent", - "hidden": true - } - } -} -``` - -Bu yalnızca otomatik menüdeki kullanıcının görünümlerinin etkileri. İzinler izin vermesine, gizli agent'lar modeli tarafından Task aracı aracılığıyla çağrılmaya devam edilebilir. - -:::note -Yalnızca `mode: subagent` agent'ları için geçerlidir. -::: - ---- - -### Görev izinleri - -`permission.task` ile bir agent'ın Task aracı aracılığıyla hangi subagent'ları çağırabileceğini kontrol edin. Esnek eşleştirme için küresel desenleri kullanır. - -```json title="opencode.json" -{ - "agent": { - "orchestrator": { - "mode": "primary", - "permission": { - "task": { - "*": "deny", - "orchestrator-*": "allow", - "code-reviewer": "ask" - } - } - } - } -} -``` - -`deny` olarak ayarlandığında, subagent Task aracı açıklamasından tamamen kaldırılır, böylece model onu çağırmaya çalışmaz. - -:::tip -Kurallar sırayla değerlendirilir ve **son eşleşen kural kazanır**. Yukarıdaki örnekte `orchestrator-planner`, hem `*` (reddet) hem de `orchestrator-*` (izin ver) ile eşleşir, ancak `orchestrator-*`, `*`'den sonra geldiğinden sonuç `allow` olur. -::: - -:::tip -Kullanıcılar, agent'ın görev izinleri bunu reddetse bile, her zaman herhangi bir subagent'ı `@` otomatik tamamlama menüsü aracılığıyla doğrudan çağırabilir. -::: - ---- - -### Renk - -Agent'ın kullanıcı arayüzündeki görsel görünümünü `color` seçeneğiyle özelleştirin. Bu, agent'ın arayüzde nasıl göründüğünü etkiler. - -geçerli bir onaltılık renk (ör. `#FF5733`) veya tema rengini kullanın: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`. - -```json title="opencode.json" -{ - "agent": { - "creative": { - "color": "#ff6b6b" - }, - "code-reviewer": { - "color": "accent" - } - } -} -``` - ---- - -### Top P - -`top_p` seçeneğiyle yanıt çeşitliliğini kontrol edin. Rastgeleliği kontrol etmek için sıcaklığa alternatif. - -```json title="opencode.json" -{ - "agent": { - "brainstorm": { - "top_p": 0.9 - } - } -} -``` - -Değerler 0,0 ile 1,0 arasında değişir. Düşük değerler daha odaklıdır, yüksek değerler ise daha çeşitlidir. - ---- - -### Ek - -Agent yapılandırmanızdaki diğer seçenekler, model seçenekleri olarak **doğrudan sağlayıcıya** iletilecektir. Bu, sağlayıcıya özgü özelliklerin kullanılmasını sağlar. - -Örneğin OpenAI'nin akıl yürütme modelleriyle akıl yürütme çabasını kontrol edebilirsiniz: - -```json title="opencode.json" {6,7} -{ - "agent": { - "deep-thinker": { - "description": "Agent that uses high reasoning effort for complex problems", - "model": "openai/gpt-5", - "reasoningEffort": "high", - "textVerbosity": "low" - } - } -} -``` - -Bu ek seçenekler modele ve sağlayıcıya özeldir. Kullanılabilir parametreler için sağlayıcınızın belgelerine bakın. - -:::tip -Mevcut modellerin listesini görmek için `opencode models` komutunu çalıştırın. -::: - ---- - -## Agent Oluşturma - -Aşağıdaki komutu kullanarak yeni agent'lar oluşturabilirsiniz: - -```bash -opencode agent create -``` - -Bu etkileşimli komut şunları sağlayacaktır: - -1. Agent'ı nereye kaydedeceğinizi sorun; küresel veya projeye özel. -2. Agent'ın ne yapması gerektiğinin açıklaması. -3. Uygun bir sistem istemi ve tanımlayıcı oluşturun. -4. Agent'ın hangi araçlara erişebileceğini seçmenize izin verin. -5. Son olarak agent yapılandırmasıyla bir Markdown dosyası oluşturun. - ---- - -## Kullanım Senaryoları - -Farklı agent'lara yönelik bazı yaygın kullanım senaryoları aşağıda verilmiştir. - -- **Build agent**: Tüm araçların etkinleştirildiği tam geliştirme çalışması -- **Plan agent**: Değişiklik yapmadan analiz ve planlama -- **Review agent**: Salt okunur erişim ve belgeleme araçlarıyla kod incelemesi -- **Debug agent**: Bash ve okuma araçları etkinken araştırmaya odaklanmıştır -- **Docs agent**: Dosya işlemleriyle ancak sistem komutları olmadan belge yazma - ---- - -## Örnekler - -Yararlı bulabileceğiniz bazı örnek agent'ları burada bulabilirsiniz. - -:::tip -Paylaşmak istediğiniz bir agent'ınız var mı? [Submit a PR](https://github.com/anomalyco/opencode). -::: - ---- - -### Dokümantasyon agent'ı - -```markdown title="~/.config/opencode/agents/docs-writer.md" ---- -description: Writes and maintains project documentation -mode: subagent -tools: - bash: false ---- - -You are a technical writer. Create clear, comprehensive documentation. - -Focus on: - -- Clear explanations -- Proper structure -- Code examples -- User-friendly language -``` - ---- - -### Güvenlik denetçisi - -```markdown title="~/.config/opencode/agents/security-auditor.md" ---- -description: Performs security audits and identifies vulnerabilities -mode: subagent -tools: - write: false - edit: false ---- - -You are a security expert. Focus on identifying potential security issues. - -Look for: - -- Input validation vulnerabilities -- Authentication and authorization flaws -- Data exposure risks -- Dependency vulnerabilities -- Configuration security issues -``` diff --git a/packages/web/src/content/docs/tr/cli.mdx b/packages/web/src/content/docs/tr/cli.mdx index ae151bd5c9..5f3cd4bfcd 100644 --- a/packages/web/src/content/docs/tr/cli.mdx +++ b/packages/web/src/content/docs/tr/cli.mdx @@ -558,6 +558,7 @@ opencode ortam değişkenleri kullanılarak yapılandırılabilir. | `OPENCODE_AUTO_SHARE` | boolean | Oturumları otomatik olarak paylaş | | `OPENCODE_GIT_BASH_PATH` | string | Windows'ta yürütülebilir Git Bash'in Yolu | | `OPENCODE_CONFIG` | string | Yapılandırma dosyasının yolu | +| `OPENCODE_TUI_CONFIG` | string | TUI yapılandırma dosyasının yolu | | `OPENCODE_CONFIG_DIR` | string | Yapılandırma dizinine giden yol | | `OPENCODE_CONFIG_CONTENT` | string | Satır içi JSON config içeriği | | `OPENCODE_DISABLE_AUTOUPDATE` | boolean | Otomatik güncelleme kontrollerini devre dışı bırak | diff --git a/packages/web/src/content/docs/tr/config.mdx b/packages/web/src/content/docs/tr/config.mdx index fe60991c62..8a769ba690 100644 --- a/packages/web/src/content/docs/tr/config.mdx +++ b/packages/web/src/content/docs/tr/config.mdx @@ -491,13 +491,15 @@ Bağlam sıkıştırma davranışını `compaction` seçeneği aracılığıyla "$schema": "https://opencode.ai/config.json", "compaction": { "auto": true, - "prune": true + "prune": true, + "reserved": 10000 } } ``` - `auto` - Bağlam dolduğunda oturumu otomatik olarak sıkıştırır (varsayılan: `true`). - `prune` - Belirteçleri kaydetmek için eski araç çıktılarını kaldırın (varsayılan: `true`). +- `reserved` - Sıkıştırma için belirteç tamponu. Sıkıştırma sırasında taşmayı önlemek için yeterli pencere bırakır. --- diff --git a/packages/web/src/content/docs/tr/custom-tools.mdx b/packages/web/src/content/docs/tr/custom-tools.mdx index cb6a12debb..87ff66d1d6 100644 --- a/packages/web/src/content/docs/tr/custom-tools.mdx +++ b/packages/web/src/content/docs/tr/custom-tools.mdx @@ -79,6 +79,32 @@ Bu iki araç oluşturur: `math_add` ve `math_multiply`. --- +#### Yerleşik araçlarla ad çakışmaları + +Özel araçlar, araç adına göre anahtarlanır. Özel bir araç yerleşik bir araçla aynı adı kullanıyorsa, özel araç önceliklidir. + +Örneğin, bu dosya yerleşik `bash` aracının yerini alır: + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +Kasıtlı olarak yerleşik bir aracı değiştirmek istemiyorsanız benzersiz adları tercih edin. Yerleşik bir aracı devre dışı bırakmak ancak geçersiz kılmak istemiyorsanız [izinleri](/docs/permissions) kullanın. +::: + +--- + ### Argümanlar Bağımsız değişken türlerini tanımlamak için yalnızca [Zod](https://zod.dev) olan `tool.schema` öğesini kullanabilirsiniz. diff --git a/packages/web/src/content/docs/tr/go.mdx b/packages/web/src/content/docs/tr/go.mdx new file mode 100644 index 0000000000..794e7f269e --- /dev/null +++ b/packages/web/src/content/docs/tr/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: Açık kodlama modelleri için düşük maliyetli abonelik. +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go, popüler açık kodlama modellerine güvenilir erişim sağlayan **aylık 10$** tutarında düşük maliyetli bir aboneliktir. + +:::note +OpenCode Go şu anda beta aşamasındadır. +::: + +Go, OpenCode içindeki diğer sağlayıcılar gibi çalışır. OpenCode Go'ya abone olur ve API anahtarınızı alırsınız. Bu **tamamen isteğe bağlıdır** ve OpenCode'u kullanmak için buna ihtiyacınız yoktur. + +Kararlı küresel erişim için ABD, AB ve Singapur'da barındırılan modellerle, öncelikli olarak uluslararası kullanıcılar için tasarlanmıştır. + +--- + +## Arka Plan + +Açık modeller gerçekten iyi hale geldi. Artık kodlama görevleri için tescilli modellere yakın performans sunuyorlar. Ve birçok sağlayıcı bunları rekabetçi bir şekilde sunabildiği için genellikle çok daha ucuzlar. + +Ancak, bunlara güvenilir ve düşük gecikmeli erişim sağlamak zor olabilir. Sağlayıcılar kalite ve kullanılabilirlik açısından farklılık gösterir. + +:::tip +OpenCode ile iyi çalışan seçkin bir model ve sağlayıcı grubunu test ettik. +::: + +Bunu düzeltmek için birkaç şey yaptık: + +1. Seçkin bir açık model grubunu test ettik ve bunları en iyi nasıl çalıştıracakları konusunda ekipleriyle görüştük. +2. Daha sonra bunların doğru şekilde sunulduğundan emin olmak için birkaç sağlayıcıyla çalıştık. +3. Son olarak, model/sağlayıcı kombinasyonunu kıyasladık ve önermekten memnuniyet duyduğumuz bir liste oluşturduk. + +OpenCode Go, bu modellere **aylık 10$** karşılığında erişmenizi sağlar. + +--- + +## Nasıl çalışır + +OpenCode Go, OpenCode'daki diğer herhangi bir sağlayıcı gibi çalışır. + +1. **OpenCode Zen**'de oturum açın, Go'ya abone olun ve API anahtarınızı kopyalayın. +2. TUI'de `/connect` komutunu çalıştırın, `OpenCode Go`yu seçin ve API anahtarınızı yapıştırın. +3. Go üzerinden kullanılabilen modellerin listesini görmek için TUI'de `/models` komutunu çalıştırın. + +:::note +Çalışma alanı başına yalnızca bir üye OpenCode Go'ya abone olabilir. +::: + +Mevcut model listesi şunları içerir: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +Test ettikçe ve yenilerini ekledikçe model listesi değişebilir. + +--- + +## Kullanım sınırları + +OpenCode Go aşağıdaki sınırları içerir: + +- **5 saatlik sınır** — 12$ kullanım +- **Haftalık sınır** — 30$ kullanım +- **Aylık sınır** — 60$ kullanım + +Sınırlar dolar değeri üzerinden tanımlanmıştır. Bu, gerçek istek sayınızın kullandığınız modele bağlı olduğu anlamına gelir. MiniMax M2.5 gibi daha ucuz modeller daha fazla isteğe izin verirken, GLM-5 gibi daha yüksek maliyetli modeller daha azına izin verir. + +Aşağıdaki tablo, tipik Go kullanım modellerine dayalı tahmini bir istek sayısı sunmaktadır: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| ------------------- | ----- | --------- | ------------ | +| 5 saat başına istek | 1.150 | 1.850 | 30.000 | +| haftalık istek | 2.880 | 4.630 | 75.000 | +| aylık istek | 5.750 | 9.250 | 150.000 | + +Tahminler gözlemlenen ortalama istek modellerine dayanmaktadır: + +- GLM-5 — İstek başına 700 girdi, 52.000 önbelleğe alınmış, 150 çıktı token'ı +- Kimi K2.5 — İstek başına 870 girdi, 55.000 önbelleğe alınmış, 200 çıktı token'ı +- MiniMax M2.5 — İstek başına 300 girdi, 55.000 önbelleğe alınmış, 125 çıktı token'ı + +Mevcut kullanımınızı **konsoldan** takip edebilirsiniz. + +:::tip +Kullanım sınırına ulaşırsanız, ücretsiz modelleri kullanmaya devam edebilirsiniz. +::: + +Erken kullanım ve geri bildirimlerden öğrendiklerimize göre kullanım sınırları değişebilir. + +--- + +### Fiyatlandırma + +OpenCode Go, **aylık 10$** tutarında bir abonelik planıdır. Aşağıda **1M token başına** fiyatlar yer almaktadır. + +| Model | Girdi | Çıktı | Önbelleğe Alınmış Okuma | +| ------------ | ----- | ----- | ----------------------- | +| GLM-5 | $1.00 | $3.20 | $0.20 | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | +| MiniMax M2.5 | $0.30 | $1.20 | $0.03 | + +--- + +### Sınırların ötesinde kullanım + +Zen bakiyenizde krediniz de varsa, konsoldaki **Bakiyeyi kullan** (Use balance) seçeneğini etkinleştirebilirsiniz. Etkinleştirildiğinde, kullanım sınırlarınıza ulaştıktan sonra Go, istekleri engellemek yerine Zen bakiyenize geri dönecektir. + +--- + +## Uç Noktalar + +Go modellerine aşağıdaki API uç noktaları üzerinden de erişebilirsiniz. + +| Model | Model ID | Endpoint | AI SDK Paketi | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +OpenCode yapılandırmanızdaki [model kimliği](/docs/config/#models), `opencode-go/` biçimini kullanır. Örneğin, Kimi K2.5 için yapılandırmanızda `opencode-go/kimi-k2.5` kullanırsınız. + +--- + +## Gizlilik + +Plan öncelikli olarak uluslararası kullanıcılar için tasarlanmıştır; modeller kararlı küresel erişim için ABD, AB ve Singapur'da barındırılmaktadır. + +Herhangi bir sorunuz varsa bizimle iletişime geçin. + +--- + +## Hedefler + +OpenCode Go'yu şu amaçlarla oluşturduk: + +1. Düşük maliyetli bir abonelikle yapay zeka kodlamasını daha fazla insan için **erişilebilir** kılmak. +2. En iyi açık kodlama modellerine **güvenilir** erişim sağlamak. +3. Kodlama ajanı kullanımı için **test edilmiş ve kıyaslanmış** modelleri seçmek. +4. OpenCode ile başka herhangi bir sağlayıcıyı kullanmanıza da izin vererek **kilitlenmeyi önlemek**. diff --git a/packages/web/src/content/docs/tr/index.mdx b/packages/web/src/content/docs/tr/index.mdx index 291d3d490c..696eddc3a1 100644 --- a/packages/web/src/content/docs/tr/index.mdx +++ b/packages/web/src/content/docs/tr/index.mdx @@ -1,13 +1,13 @@ --- title: Giriş -description: opencode kullanmaya başlayın. +description: OpenCode kullanmaya başlayın. --- import { Tabs, TabItem } from "@astrojs/starlight/components" import config from "../../../../config.mjs" export const console = config.console -[**opencode**](/) açık kaynaklı bir AI kodlama ajanıdır. Terminal tabanlı bir arayüz, masaüstü uygulaması veya IDE uzantısı olarak mevcuttur. +[**OpenCode**](/) açık kaynaklı bir AI kodlama ajanıdır. Terminal tabanlı bir arayüz, masaüstü uygulaması veya IDE uzantısı olarak mevcuttur. ![opencode TUI with the opencode theme](../../../assets/lander/screenshot.png) @@ -17,11 +17,11 @@ Başlayalım. #### Ön koşullar -opencode'u terminalinizde kullanmak için ihtiyacınız olacak: +OpenCode'u terminalinizde kullanmak için ihtiyacınız olacak: 1. Şu gibi modern bir terminal emülatörü: - - [WezTerm](https://wezterm.org), cross-platform - - [Alacritty](https://alacritty.org), cross-platform + - [WezTerm](https://wezterm.org), cross-platform (tüm platformlarda) + - [Alacritty](https://alacritty.org), cross-platform (tüm platformlarda) - [Ghostty](https://ghostty.org), Linux ve macOS - [Kitty](https://sw.kovidgoyal.net/kitty/), Linux ve macOS @@ -31,7 +31,7 @@ opencode'u terminalinizde kullanmak için ihtiyacınız olacak: ## Kurulum -opencode'u kurmanın en kolay yolu kurulum betiğidir. +OpenCode'u kurmanın en kolay yolu kurulum betiğidir. ```bash curl -fsSL https://opencode.ai/install | bash @@ -79,7 +79,7 @@ Ayrıca aşağıdaki komutlarla da yükleyebilirsiniz: brew install anomalyco/tap/opencode ``` - > En güncel sürümler için opencode tap'ini kullanmanızı öneririz. Resmi `brew install opencode` formülü Homebrew ekibi tarafından korunur ve daha sık güncellenir. + > En güncel sürümler için OpenCode tap'ini kullanmanızı öneririz. Resmi `brew install opencode` formülü Homebrew ekibi tarafından korunur ve daha sık güncellenir. - **Paru'yu Arch Linux'ta kullanma** @@ -91,7 +91,7 @@ Ayrıca aşağıdaki komutlarla da yükleyebilirsiniz: #### Windows :::tip[Önerilen: WSL kullanın] -Windows'ta en iyi deneyim için [Windows Subsystem for Linux (WSL)](/docs/windows-wsl) kullanılmasını öneririz. Daha iyi performans ve opencode'un özellikleriyle tam uyumluluğu sağlar. +Windows'ta en iyi deneyim için [Windows Subsystem for Linux (WSL)](/docs/windows-wsl) kullanılmasını öneririz. Daha iyi performans ve OpenCode'un özellikleriyle tam uyumluluğu sağlar. ::: - **Chocolatey Kullanımı** @@ -124,7 +124,7 @@ Windows'ta en iyi deneyim için [Windows Subsystem for Linux (WSL)](/docs/window docker run -it --rm ghcr.io/anomalyco/opencode ``` -opencode'un Bun kullanılarak Windows'a yüklenmesine yönelik destek şu anda devam etmektedir. +OpenCode'un Bun kullanılarak Windows'a yüklenmesine yönelik destek şu anda devam etmektedir. İkili dosyayı [Releases](https://github.com/anomalyco/opencode/releases)'dan da alabilirsiniz. @@ -132,12 +132,12 @@ opencode'un Bun kullanılarak Windows'a yüklenmesine yönelik destek şu anda d ## Yapılandırma -opencode ile herhangi bir LLM sağlayıcısının API anahtarlarını yapılandırarak kullanabilirsiniz. +OpenCode ile herhangi bir LLM sağlayıcısının API anahtarlarını yapılandırarak kullanabilirsiniz. LLM sağlayıcılarını kullanmaya yeni başlıyorsanız, [OpenCode Zen](/docs/zen) kullanmanızı öneririz. -opencode ekibi tarafından test edilmiş ve doğrulanmış modellerin seçilmiş bir listesidir. +OpenCode ekibi tarafından test edilmiş ve doğrulanmış modellerin seçilmiş bir listesidir. -1. TUI'de `/connect` komutunu çalıştırın, opencode'u seçin ve [opencode.ai/auth](https://opencode.ai/auth)'ye gidin. +1. TUI'de `/connect` komutunu çalıştırın, OpenCode'u seçin ve [opencode.ai/auth](https://opencode.ai/auth)'ye gidin. ```txt /connect @@ -160,39 +160,37 @@ Alternatif olarak diğer sağlayıcılardan birini seçebilirsiniz. [Daha fazla ## Başlatma -Artık bir sağlayıcı yapılandırdığınıza göre, bir projeye gidebilirsiniz. -üzerinde çalışmak istiyorsun. +Artık bir sağlayıcı yapılandırdığınıza göre, üzerinde çalışmak istediğiniz bir projeye gidebilirsiniz. ```bash cd /path/to/project ``` -Ve opencode'u çalıştırın. +Ve OpenCode'u çalıştırın. ```bash opencode ``` -Daha sonra aşağıdaki komutu çalıştırarak proje için opencode'u başlatın. +Daha sonra aşağıdaki komutu çalıştırarak proje için OpenCode'u başlatın. ```bash frame="none" /init ``` -Bu, opencode'un projenizi analiz etmesini ve bir `AGENTS.md` dosyası oluşturmasını sağlayacaktır. -proje kökü. +Bu, OpenCode'un projenizi analiz etmesini ve bir `AGENTS.md` proje kökünde dosyası oluşturmasını sağlayacaktır. :::tip Projenizin `AGENTS.md` dosyasını Git'e göndermelisiniz. ::: -Bu, opencode'un proje yapısını ve kullanılan kodlama kalıplarını anlamasına yardımcı olur. +Bu, OpenCode'un proje yapısını ve kullanılan kodlama kalıplarını anlamasına yardımcı olur. --- ## Kullanım -Artık projeniz üzerinde çalışmak için opencode'u kullanmaya hazırsınız. Dilediğiniz soruyu sorabilirsiniz. +Artık projeniz üzerinde çalışmak için OpenCode'u kullanmaya hazırsınız. Dilediğiniz soruyu sorabilirsiniz. AI kodlama ajanını kullanmaya yeniyseniz aşağıdaki örnekler yardımcı olabilir. @@ -200,7 +198,7 @@ AI kodlama ajanını kullanmaya yeniyseniz aşağıdaki örnekler yardımcı ola ### Soru Sorma -opencode'dan kod tabanını size açıklamasını isteyebilirsiniz. +OpenCode'dan kod tabanını size açıklamasını isteyebilirsiniz. :::tip Projedeki dosyaları bulanık aramak için `@` tuşunu kullanın. @@ -216,14 +214,14 @@ Kod tabanının üzerinde çalışmadığınız bir kısmı varsa bu yararlı ol ### Özellik Ekleme -opencode'dan projenize yeni özellikler eklemesini isteyebilirsiniz. Yine de öncelikle ondan bir plan oluşturmasını istemenizi öneririz. +OpenCode'dan projenize yeni özellikler eklemesini isteyebilirsiniz. Yine de öncelikle ondan bir plan oluşturmasını istemenizi öneririz. 1. **Bir plan oluşturun** - opencode, değişiklik yapma özelliğini kapatan bir \_Plan modu_na sahiptir. + OpenCode, değişiklik yapma özelliğini kapatan bir \_Plan modu\_\na sahiptir. Bu modda, özelliğin nasıl uygulanacağını önerir. - **Sekme** tuşunu kullanarak buna geçin. Bunun için sağ alt köşede bir gösterge göreceksiniz. + **Tab** tuşunu kullanarak buna geçin. Bunun için sağ alt köşede bir gösterge göreceksiniz. ```bash frame="none" title="Plan moduna geç" @@ -237,16 +235,13 @@ opencode'dan projenize yeni özellikler eklemesini isteyebilirsiniz. Yine de ön From this screen, the user can undelete a note or permanently delete it. ``` - opencode'un isteğinizi anlaması için yeterli ayrıntı verin. + OpenCode'un isteğinizi anlaması için yeterli ayrıntı verin. Ekibinizdeki junior bir geliştiriciyle konuşur gibi yazmak genelde iyi sonuç verir. :::tip - opencode'a bol bağlam ve örnek verin. + OpenCode'a ne istediğinizi anlamasına yardımcı olacak bol miktarda bağlam ve örnek verin. ::: - opencode verdiğiniz görselleri tarayıp prompt'a ekleyebilir. - Bunu bir görseli terminale sürükleyip bırakarak yapabilirsiniz. - 2. **Planı yineleyin** Size bir plan sunduğunda ona geri bildirimde bulunabilir veya daha fazla ayrıntı ekleyebilirsiniz. @@ -260,12 +255,12 @@ opencode'dan projenize yeni özellikler eklemesini isteyebilirsiniz. Yine de ön İsteme eklemek için görüntüleri terminale sürükleyip bırakın. ::: - opencode verdiğiniz görselleri tarayıp prompt'a ekleyebilir. + OpenCode verdiğiniz görselleri tarayıp prompt'a ekleyebilir. Bunu bir görseli terminale sürükleyip bırakarak yapabilirsiniz. 3. **Özelliği oluşturun** - Planı yeterli bulduğunuzda **Sekme** tuşuna tekrar basarak \_Build modu_na dönün. + Planı yeterli bulduğunuzda **Tab** tuşuna tekrar basarak \_Build modu\_\na dönün. ```bash frame="none" @@ -281,7 +276,7 @@ opencode'dan projenize yeni özellikler eklemesini isteyebilirsiniz. Yine de ön ### Değişiklik Yapma -Daha basit değişikliklerde, önce planı incelemeden opencode'dan doğrudan değişiklik yapmasını isteyebilirsiniz. +Daha basit değişikliklerde, önce planı incelemeden OpenCode'dan doğrudan değişiklik yapmasını isteyebilirsiniz. ```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts" We need to add authentication to the /settings route. Take a look at how this is @@ -289,32 +284,31 @@ handled in the /notes route in @packages/functions/src/notes.ts and implement the same logic in @packages/functions/src/settings.ts ``` -opencode'un doğru değişiklikleri yapması için yeterli ayrıntı verdiğinizden emin olun. +OpenCode'un doğru değişiklikleri yapması için yeterli ayrıntı verdiğinizden emin olun. --- ### Değişiklikleri Geri Alma -Diyelim ki opencode'dan bazı değişiklikler yapmasını istediniz. +Diyelim ki OpenCode'dan bazı değişiklikler yapmasını istediniz. ```txt frame="none" "@packages/functions/src/api/index.ts" Can you refactor the function in @packages/functions/src/api/index.ts? ``` -Ama istediğinin bu olmadığını anlıyorsun. Değişiklikleri **geri alabilirsiniz** -`/undo` komutunu kullanarak. +Ama istediğinin bu olmadığını anlıyorsun. `/undo` komutunu kullanarak değişiklikleri **geri alabilirsiniz**. ```bash frame="none" /undo ``` -opencode değişiklikleri geri alır ve orijinal mesajınızı tekrar gösterir. +OpenCode değişiklikleri geri alır ve orijinal mesajınızı tekrar gösterir. ```txt frame="none" "@packages/functions/src/api/index.ts" Can you refactor the function in @packages/functions/src/api/index.ts? ``` -Buradan komut isteminde ince ayar yapabilir ve opencode'dan tekrar denemesini isteyebilirsiniz. +Buradan komut isteminde ince ayar yapabilir ve OpenCode'dan tekrar denemesini isteyebilirsiniz. :::tip Birden çok değişikliği geri almak için `/undo` komutunu birden çok kez çalıştırabilirsiniz. @@ -330,7 +324,7 @@ Veya `/redo` komutunu kullanarak değişiklikleri **yeniden yapabilirsiniz**. ## Paylaşma -opencode ile yaptığınız görüşmeleri [ekibinizle paylaşabilirsiniz](/docs/share). +OpenCode ile yaptığınız görüşmeleri [ekibinizle paylaşabilirsiniz](/docs/share). ```bash frame="none" /share @@ -342,12 +336,12 @@ Bu, mevcut konuşmaya bir bağlantı oluşturacak ve bunu panonuza kopyalayacakt Konuşmalar varsayılan olarak paylaşılmaz. ::: -İşte opencode'lu bir [örnek konuşma](https://opencode.ai/s/4XP1fce5). +İşte OpenCode ile bir [örnek konuşma](https://opencode.ai/s/4XP1fce5). --- ## Özelleştirme -İşte bu kadar! Artık opencode'u kullanma konusunda profesyonelsiniz. +İşte bu kadar! Artık OpenCode'u kullanma konusunda profesyonelsiniz. -Kendinize göre uyarlamak için [tema seçebilir](/docs/themes), [tuş atamalarını özelleştirebilir](/docs/keybinds), [kod biçimlendirici ayarlayabilir](/docs/formatters), [özel komutlar oluşturabilir](/docs/commands) veya [opencode config](/docs/config) ile oynayabilirsiniz. +Kendinize göre uyarlamak için [tema seçebilir](/docs/themes), [tuş atamalarını özelleştirebilir](/docs/keybinds), [kod biçimlendirici ayarlayabilir](/docs/formatters), [özel komutlar oluşturabilir](/docs/commands) veya [OpenCode config](/docs/config) ile oynayabilirsiniz. diff --git a/packages/web/src/content/docs/tr/keybinds.mdx b/packages/web/src/content/docs/tr/keybinds.mdx index 9a22c329cc..bea63a3550 100644 --- a/packages/web/src/content/docs/tr/keybinds.mdx +++ b/packages/web/src/content/docs/tr/keybinds.mdx @@ -3,11 +3,11 @@ title: Tuş atamaları description: Tuş bağlantılarınızı özelleştirin. --- -opencode, opencode yapılandırması aracılığıyla özelleştirebileceğiniz bir tuş bağlantıları listesine sahiptir. +opencode, `tui.json` aracılığıyla özelleştirebileceğiniz bir tuş bağlantıları listesine sahiptir. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -119,9 +119,9 @@ Tuş atamalarınız için lider anahtar kullanmanıza gerek yoktur ancak bunu ya Anahtarı yapılandırmanıza "none" değeriyle ekleyerek bir tuş atamasını devre dışı bırakabilirsiniz. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/tr/lsp.mdx b/packages/web/src/content/docs/tr/lsp.mdx index db74211385..52a95d1c3c 100644 --- a/packages/web/src/content/docs/tr/lsp.mdx +++ b/packages/web/src/content/docs/tr/lsp.mdx @@ -1,15 +1,15 @@ --- title: LSP Sunucuları -description: opencode, LSP sunucularınızla bütünleşir. +description: OpenCode, LSP sunucularınızla bütünleşir. --- -opencode, LLM'in kod tabanınızla etkileşime girmesine yardımcı olmak için Dil Sunucusu Protokolünüzle (LSP) bütünleşir. LLM'ye geri bildirim sağlamak için tanılamayı kullanır. +OpenCode, LLM'in kod tabanınızla etkileşime girmesine yardımcı olmak için Dil Sunucusu Protokolünüzle (LSP) bütünleşir. LLM'ye geri bildirim sağlamak için tanılamayı kullanır. --- ## Yerleşik -opencode, popüler diller için çeşitli yerleşik LSP sunucularıyla birlikte gelir: +OpenCode, popüler diller için çeşitli yerleşik LSP sunucularıyla birlikte gelir: | LSP Sunucu | Uzantılar | Gereksinimler | | ------------------ | ------------------------------------------------------------------- | --------------------------------------------------------------------- | @@ -27,6 +27,7 @@ opencode, popüler diller için çeşitli yerleşik LSP sunucularıyla birlikte | gopls | .go | `go` komutu mevcut | | hls | .hs, .lhs | `haskell-language-server-wrapper` komutu mevcut | | jdtls | .java | `Java SDK (version 21+)` kurulu | +| julials | .jl | `julia` ve `LanguageServer.jl` kurulu | | kotlin-ls | .kt, .kts | Kotlin projeleri için otomatik kurulumlar | | lua-ls | .lua | Lua projeleri için otomatik kurulumlar | | nixd | .nix | `nixd` komutu mevcut | @@ -56,7 +57,7 @@ Yukarıdaki dosya uzantılarından biri tespit edildiğinde ve gereksinimler kar ## Nasıl Çalışır? -Opencode bir dosyayı açtığında: +opencode bir dosyayı açtığında: 1. Dosya uzantısını tüm etkin LSP sunucularına göre kontrol eder. 2. Henüz çalışmıyorsa uygun LSP sunucusunu başlatır. @@ -182,7 +183,7 @@ Komutu ve dosya uzantılarını belirterek özel LSP sunucuları ekleyebilirsini PHP Intelephense, bir lisans anahtarı aracılığıyla premium özellikler sunar. Anahtarı (yalnızca) şu adresteki bir metin dosyasına yerleştirerek bir lisans anahtarı sağlayabilirsiniz: -- MacOS/Linux'ta: `$HOME/intelephense/license.txt` +- macOS/Linux'ta: `$HOME/intelephense/license.txt` - Windows'ta: `%USERPROFILE%/intelephense/license.txt` Dosya, ek içerik olmadan yalnızca lisans anahtarını içermelidir. diff --git a/packages/web/src/content/docs/tr/plugins.mdx b/packages/web/src/content/docs/tr/plugins.mdx index 0b24e48c35..4926f5f70e 100644 --- a/packages/web/src/content/docs/tr/plugins.mdx +++ b/packages/web/src/content/docs/tr/plugins.mdx @@ -1,9 +1,9 @@ --- title: Eklentiler -description: opencode'u genişletmek için kendi eklentilerinizi yazın. +description: OpenCode'u genişletmek için kendi eklentilerinizi yazın. --- -Eklentiler, çeşitli olaylara bağlanarak ve davranışı özelleştirerek opencode'u genişletmenize olanak tanır. Yeni özellikler eklemek, harici hizmetlerle entegrasyon sağlamak veya opencode'un varsayılan davranışını değiştirmek için eklentiler oluşturabilirsiniz. +Eklentiler, çeşitli olaylara bağlanarak ve davranışı özelleştirerek OpenCode'u genişletmenize olanak tanır. Yeni özellikler eklemek, harici hizmetlerle entegrasyon sağlamak veya OpenCode'un varsayılan davranışını değiştirmek için eklentiler oluşturabilirsiniz. Örnekler için topluluk tarafından oluşturulan [eklentilere](/docs/ecosystem#plugins) göz atın. @@ -47,7 +47,7 @@ Hem normal hem de kapsamlı npm paketleri desteklenir. **npm eklentileri** başlangıçta Bun kullanılarak otomatik olarak yüklenir. Paketler ve bağımlılıkları `~/.cache/opencode/node_modules/`'da önbelleğe alınır. -**Yerel eklentiler** doğrudan eklenti dizininden yüklenir. Harici paketleri kullanmak için, sisteminizin dizininde bir `package.json` oluşturmanız (bkz. [Bağımlılıklar](#dependencies)) veya eklentiyi npm ve [add it to your config](/docs/config#plugins)'de yayınlamanız gerekir. +**Yerel eklentiler** doğrudan eklenti dizininden yüklenir. Harici paketleri kullanmak için, sisteminizin dizininde bir `package.json` oluşturmanız (bkz. [Bağımlılıklar](#dependencies)) veya eklentiyi npm ve [yapılandırmanıza eklemeniz](/docs/config#plugins) gerekir. --- @@ -66,8 +66,7 @@ Aynı ad ve sürüme sahip yinelenen npm paketleri bir kez yüklenir. Ancak benz ## Eklenti oluşturma -Eklenti, bir veya daha fazla eklentiyi dışa aktaran bir **JavaScript/TypeScript modülüdür** -işlevler. Her işlev bir bağlam nesnesi alır ve bir kanca nesnesi döndürür. +Eklenti, bir veya daha fazla eklenti işlevini dışa aktaran bir **JavaScript/TypeScript modülüdür**. Her işlev bir bağlam nesnesi alır ve bir kanca nesnesi döndürür. --- @@ -83,7 +82,7 @@ Yerel eklentiler ve özel araçlar harici npm paketlerini kullanabilir. İhtiyac } ``` -opencode bunları yüklemek için başlangıçta `bun install` komutunu çalıştırır. Eklentileriniz ve araçlarınız daha sonra bunları içe aktarabilir. +OpenCode bunları yüklemek için başlangıçta `bun install` komutunu çalıştırır. Eklentileriniz ve araçlarınız daha sonra bunları içe aktarabilir. ```ts title=".opencode/plugins/my-plugin.ts" import { escape } from "shescape" @@ -116,9 +115,9 @@ export const MyPlugin = async ({ project, client, $, directory, worktree }) => { Eklenti işlevi şunları alır: - `project`: Mevcut proje bilgisi. -- `directory`: güncel çalışma dizini. +- `directory`: Güncel çalışma dizini. - `worktree`: Git çalışma ağacı yolu. -- `client`: Yapay zeka ile etkileşime geçmek için opencode'lu bir SDK istemcisi. +- `client`: Yapay zeka ile etkileşim kurmak için bir OpenCode SDK istemcisi. - `$`: Bun'un komutları yürütmek için kullandığı [shell API](https://bun.com/docs/runtime/shell). --- @@ -211,7 +210,7 @@ Eklentiler aşağıdaki Örnekler bölümünde görüldüğü gibi etkinliklere ## Örnekler -opencode'u genişletmek için kullanabileceğiniz bazı eklenti örneklerini burada bulabilirsiniz. +OpenCode'u genişletmek için kullanabileceğiniz bazı eklenti örneklerini burada bulabilirsiniz. --- @@ -232,17 +231,17 @@ export const NotificationPlugin = async ({ project, client, $, directory, worktr } ``` -MacOS'ta AppleScript'i çalıştırmak için `osascript` kullanıyoruz. Burada bildirim göndermek için kullanıyoruz. +macOS'ta AppleScript'i çalıştırmak için `osascript` kullanıyoruz. Burada bildirim göndermek için kullanıyoruz. :::note -opencode masaüstü uygulamasını kullanıyorsanız yanıt hazır olduğunda veya oturum hataları oluştuğunda otomatik olarak sistem bildirimleri gönderebilir. +OpenCode masaüstü uygulamasını kullanıyorsanız yanıt hazır olduğunda veya oturum hataları oluştuğunda otomatik olarak sistem bildirimleri gönderebilir. ::: --- ### .env Koruması -opencode'un `.env` dosyalarını okumasını önleyin: +OpenCode'un `.env` dosyalarını okumasını önleyin: ```javascript title=".opencode/plugins/env-protection.js" export const EnvProtection = async ({ project, client, $, directory, worktree }) => { @@ -277,7 +276,7 @@ export const InjectEnvPlugin = async () => { ### Özel araçlar -Eklentiler ayrıca opencode'a özel araçlar da ekleyebilir: +Eklentiler ayrıca OpenCode'a özel araçlar da ekleyebilir: ```ts title=".opencode/plugins/custom-tools.ts" import { type Plugin, tool } from "@opencode-ai/plugin" @@ -300,19 +299,23 @@ export const CustomToolsPlugin: Plugin = async (ctx) => { } ``` -`tool` yardımcısı, opencode'un çağırabileceği özel bir araç oluşturur. Bir Zod şeması işlevini alır ve aşağıdakileri içeren bir araç tanımı döndürür: +`tool` yardımcısı, OpenCode'un çağırabileceği özel bir araç oluşturur. Bir Zod şeması işlevini alır ve aşağıdakileri içeren bir araç tanımı döndürür: - `description`: Araç ne yapar? - `args`: Aracın argümanları için Zod şeması - `execute`: Araç çağrıldığında çalışan fonksiyon -Özel araçlarınız, yerleşik araçların yanı sıra kod açmaya da hazır olacaktır. +Özel araçlarınız, yerleşik araçların yanı sıra OpenCode'a da hazır olacaktır. + +:::note +Eğer bir eklenti aracı yerleşik bir araçla aynı adı kullanırsa, eklenti aracı öncelik kazanır. +::: --- ### Günlüğe kaydetme -Yapılandırılmış günlük kaydı için `client.app.log()` yerine `console.log` kullanın: +Yapılandırılmış günlük kaydı için `console.log` yerine `client.app.log()` kullanın: ```ts title=".opencode/plugins/my-plugin.ts" export const MyPlugin = async ({ client }) => { @@ -327,7 +330,7 @@ export const MyPlugin = async ({ client }) => { } ``` -Seviyeler: `debug`, `info`, `warn`, `error`. Ayrıntılar için [SDK documentation](https://opencode.ai/docs/sdk)'e bakın. +Seviyeler: `debug`, `info`, `warn`, `error`. Ayrıntılar için [SDK belgelerine](https://opencode.ai/docs/sdk) bakın. --- diff --git a/packages/web/src/content/docs/tr/providers.mdx b/packages/web/src/content/docs/tr/providers.mdx index efe5ff9afa..1ddc65131c 100644 --- a/packages/web/src/content/docs/tr/providers.mdx +++ b/packages/web/src/content/docs/tr/providers.mdx @@ -84,6 +84,37 @@ opencode'daki diğer sağlayıcılar gibi çalışır ve kullanımı tamamen ist --- +## OpenCode Go + +OpenCode Go, opencode ile iyi çalıştığı test edilmiş ve doğrulanmış, opencode ekibi tarafından sağlanan popüler açık kodlama modellerine güvenilir erişim sağlayan düşük maliyetli bir abonelik planıdır. + +1. TUI'de `/connect` komutunu çalıştırın, `OpenCode Go`'yu seçin ve [opencode.ai/auth](https://opencode.ai/zen) adresine gidin. + + ```txt + /connect + ``` + +2. Oturum açın, fatura ayrıntılarınızı ekleyin ve API anahtarınızı kopyalayın. + +3. API anahtarınızı yapıştırın. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. Önerdiğimiz modellerin listesini görmek için TUI'de `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +opencode'daki diğer sağlayıcılar gibi çalışır ve kullanımı tamamen isteğe bağlıdır. + +--- + ## Dizin Sağlayıcılardan bazılarına ayrıntılı olarak bakalım. Bir sağlayıcı eklemek istiyorsanız @@ -1481,6 +1512,39 @@ SAP AI Core, birleşik bir platform aracılığıyla OpenAI, Anthropic, Google, --- +### STACKIT + +STACKIT AI Model Serving, Llama, Mistral ve Qwen gibi LLM'lere odaklanarak, Avrupa altyapısında maksimum veri egemenliğine sahip AI modelleri için tam olarak yönetilen bağımsız barındırma ortamı sağlar. + +1. [STACKIT Portal](https://portal.stackit.cloud) adresine gidin, **AI Model Serving**'e gidin ve projeniz için bir yetkilendirme belirteci oluşturun. + + :::tip + Yetkilendirme belirteçleri oluşturmadan önce bir STACKIT müşteri hesabına, kullanıcı hesabına ve projesine ihtiyacınız vardır. + ::: + +2. `/connect` komutunu çalıştırın ve **STACKIT**'i arayın. + + ```txt + /connect + ``` + +3. STACKIT AI Model Serving yetkilendirme belirtecinizi girin. + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. _Qwen3-VL 235B_ veya _Llama 3.3 70B_ gibi mevcut modellerden seçim yapmak için `/models` komutunu çalıştırın. + + ```txt + /models + ``` + +--- + ### OVHcloud AI Endpoints 1. [OVHcloud panel](https://ovh.com/manager)'a gidin. `Public Cloud` bölümüne gidin, `AI & Machine Learning` > `AI Endpoints` ve `API Keys` sekmesinde **Yeni bir API anahtarı oluştur**'u tıklayın. diff --git a/packages/web/src/content/docs/tr/sdk.mdx b/packages/web/src/content/docs/tr/sdk.mdx index b5ba99f437..44c910b1cb 100644 --- a/packages/web/src/content/docs/tr/sdk.mdx +++ b/packages/web/src/content/docs/tr/sdk.mdx @@ -117,6 +117,78 @@ try { --- +## Yapılandırılmış Çıktı + +Bir JSON şeması ile `format` belirterek modelden yapılandırılmış JSON çıktısı isteyebilirsiniz. Model, şemanızla eşleşen doğrulanmış JSON'u döndürmek için bir `StructuredOutput` aracı kullanacaktır. + +### Temel Kullanım + +```typescript +const result = await client.session.prompt({ + path: { id: sessionId }, + body: { + parts: [{ type: "text", text: "Anthropic'i araştırın ve şirket bilgileri sağlayın" }], + format: { + type: "json_schema", + schema: { + type: "object", + properties: { + company: { type: "string", description: "Şirket adı" }, + founded: { type: "number", description: "Kuruluş yılı" }, + products: { + type: "array", + items: { type: "string" }, + description: "Ana ürünler", + }, + }, + required: ["company", "founded"], + }, + }, + }, +}) + +// Yapılandırılmış çıktıya erişin +console.log(result.data.info.structured_output) +// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] } +``` + +### Çıktı Format Türleri + +| Tür | Açıklama | +| ------------- | ------------------------------------------------------------- | +| `text` | Varsayılan. Standart metin yanıtı (yapılandırılmış çıktı yok) | +| `json_schema` | Sağlanan şema ile eşleşen doğrulanmış JSON döndürür | + +### JSON Şema Formatı + +`type: 'json_schema'` kullanırken şunları sağlayın: + +| Alan | Tür | Açıklama | +| ------------ | --------------- | ------------------------------------------------------------- | +| `type` | `'json_schema'` | Gerekli. JSON şema modunu belirtir | +| `schema` | `object` | Gerekli. Çıktı yapısını tanımlayan JSON Şema nesnesi | +| `retryCount` | `number` | İsteğe bağlı. Doğrulama yeniden deneme sayısı (varsayılan: 2) | + +### Hata Yönetimi + +Model, tüm yeniden denemelerden sonra geçerli bir yapılandırılmış çıktı üretemezse, yanıt bir `StructuredOutputError` içerecektir: + +```typescript +if (result.data.info.error?.name === "StructuredOutputError") { + console.error("Yapılandırılmış çıktı üretilemedi:", result.data.info.error.message) + console.error("Denemeler:", result.data.info.error.retries) +} +``` + +### En İyi Uygulamalar + +1. **Açık açıklamalar sağlayın**: Modelin hangi verileri çıkaracağını anlamasına yardımcı olmak için şema özelliklerinde +2. **`required` kullanın**: Hangi alanların mevcut olması gerektiğini belirtmek için +3. **Şemaları odaklı tutun**: Karmaşık iç içe geçmiş şemaların model tarafından doğru doldurulması daha zor olabilir +4. **Uygun `retryCount` ayarlayın**: Karmaşık şemalar için artırın, basit olanlar için azaltın + +--- + ## API'ler SDK, tüm sunucu API'lerini type-safe bir istemci aracılığıyla sunar. @@ -226,27 +298,27 @@ const { providers, default: defaults } = await client.config.providers() ### Oturumlar -| Yöntem | Açıklama | Notlar | -| ---------------------------------------------------------- | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `session.list()` | Oturumları listele | Session[] döndürür | -| `session.get({ path })` | Oturum al | Session döndürür | -| `session.children({ path })` | Alt oturumları listele | Session[] döndürür | -| `session.create({ body })` | Oturum oluştur | Session döndürür | -| `session.delete({ path })` | Oturum sil | `boolean` döndürür | -| `session.update({ path, body })` | Oturum özelliklerini güncelle | Session döndürür | -| `session.init({ path, body })` | Uygulamayı analiz et ve `AGENTS.md` oluştur | `boolean` döndürür | -| `session.abort({ path })` | Çalışan bir oturumu iptal et | `boolean` döndürür | -| `session.share({ path })` | Oturum paylaş | Session döndürür | -| `session.unshare({ path })` | Oturum paylaşımını kaldır | Session döndürür | -| `session.summarize({ path, body })` | Oturumu özetle | `boolean` döndürür | -| `session.messages({ path })` | Oturumdaki mesajları listele | `{ info: `Message`, parts: `Part[]`}[]` döndürür | -| `session.message({ path })` | Mesaj ayrıntılarını al | `{ info: `Message`, parts: `Part[]`}` döndürür | -| `session.prompt({ path, body })` | İstem mesajı gönder | `body.noReply: true` UserMessage (yalnızca bağlam) döndürür. Varsayılan olarak AI yanıtıyla AssistantMessage döndürür | -| `session.command({ path, body })` | Oturuma komut gönder | `{ info: `AssistantMessage`, parts: `Part[]`}` döndürür | -| `session.shell({ path, body })` | Bir kabuk komutu çalıştır | AssistantMessage döndürür | -| `session.revert({ path, body })` | Bir mesajı geri al | Session döndürür | -| `session.unrevert({ path })` | Geri alınan mesajları geri yükle | Session döndürür | -| `postSessionByIdPermissionsByPermissionId({ path, body })` | Bir izin isteğine yanıt ver | `boolean` döndürür | +| Yöntem | Açıklama | Notlar | +| ---------------------------------------------------------- | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `session.list()` | Oturumları listele | Session[] döndürür | +| `session.get({ path })` | Oturum al | Session döndürür | +| `session.children({ path })` | Alt oturumları listele | Session[] döndürür | +| `session.create({ body })` | Oturum oluştur | Session döndürür | +| `session.delete({ path })` | Oturum sil | `boolean` döndürür | +| `session.update({ path, body })` | Oturum özelliklerini güncelle | Session döndürür | +| `session.init({ path, body })` | Uygulamayı analiz et ve `AGENTS.md` oluştur | `boolean` döndürür | +| `session.abort({ path })` | Çalışan bir oturumu iptal et | `boolean` döndürür | +| `session.share({ path })` | Oturum paylaş | Session döndürür | +| `session.unshare({ path })` | Oturum paylaşımını kaldır | Session döndürür | +| `session.summarize({ path, body })` | Oturumu özetle | `boolean` döndürür | +| `session.messages({ path })` | Oturumdaki mesajları listele | `{ info: `Message`, parts: `Part[]`}[]` döndürür | +| `session.message({ path })` | Mesaj ayrıntılarını al | `{ info: `Message`, parts: `Part[]`}` döndürür | +| `session.prompt({ path, body })` | İstem mesajı gönder | `body.noReply: true` UserMessage (yalnızca bağlam) döndürür. Varsayılan olarak AI yanıtıyla AssistantMessage döndürür. [yapılandırılmış çıktı](#yapılandırılmış-çıktı) için `body.outputFormat` destekler | +| `session.command({ path, body })` | Oturuma komut gönder | `{ info: `AssistantMessage`, parts: `Part[]`}` döndürür | +| `session.shell({ path, body })` | Bir kabuk komutu çalıştır | AssistantMessage döndürür | +| `session.revert({ path, body })` | Bir mesajı geri al | Session döndürür | +| `session.unrevert({ path })` | Geri alınan mesajları geri yükle | Session döndürür | +| `postSessionByIdPermissionsByPermissionId({ path, body })` | Bir izin isteğine yanıt ver | `boolean` döndürür | --- diff --git a/packages/web/src/content/docs/tr/themes.mdx b/packages/web/src/content/docs/tr/themes.mdx index 93911315f2..1511e2b921 100644 --- a/packages/web/src/content/docs/tr/themes.mdx +++ b/packages/web/src/content/docs/tr/themes.mdx @@ -61,11 +61,11 @@ Sistem teması şu kullanıcılar için idealdir: ## Tema kullanımı -`/theme` komutuyla tema seçicisini açıp tema seçebilirsiniz. İsterseniz [config](/docs/config) dosyanızda da belirtebilirsiniz. +`/theme` komutuyla tema seçicisini açıp tema seçebilirsiniz. İsterseniz `tui.json` içinde de belirtebilirsiniz. -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` diff --git a/packages/web/src/content/docs/tr/tui.mdx b/packages/web/src/content/docs/tr/tui.mdx index 2bd5db8f5d..55305f3672 100644 --- a/packages/web/src/content/docs/tr/tui.mdx +++ b/packages/web/src/content/docs/tr/tui.mdx @@ -1,25 +1,25 @@ --- title: TUI -description: opencode terminal arayuzunu kullanin. +description: OpenCode terminal kullanıcı arayüzünü kullanma. --- import { Tabs, TabItem } from "@astrojs/starlight/components" -opencode, projelerinizde LLM ile calismak icin etkilesimli bir terminal arayuzu (TUI) sunar. +OpenCode, projelerinizde LLM ile çalışmak için etkileşimli bir terminal arayüzü (TUI) sunar. -opencode'u calistirdiginizda mevcut dizin icin TUI baslar. +OpenCode'u çalıştırdığınızda mevcut dizin için TUI başlar. ```bash opencode ``` -Isterseniz belirli bir calisma dizini icin de baslatabilirsiniz. +İsterseniz belirli bir çalışma dizini için de başlatabilirsiniz. ```bash opencode /path/to/project ``` -TUI icinde bir mesaj yazarak istem gonderebilirsiniz. +TUI içine girdiğinizde, bir mesajla istem gönderebilirsiniz. ```text Give me a quick summary of the codebase. @@ -27,51 +27,51 @@ Give me a quick summary of the codebase. --- -## Dosya referanslari +## Dosya referansları -Mesajlarinizda `@` kullanarak dosyalara referans verebilirsiniz. Bu, mevcut calisma dizininde bulanik dosya aramasi yapar. +Mesajlarınızda `@` kullanarak dosyalara referans verebilirsiniz. Bu, mevcut çalışma dizininde bulanık dosya araması yapar. :::tip -Mesajlarinizda dosyalara referans vermek icin `@` kullanabilirsiniz. +Mesajlarınızda dosyalara referans vermek için `@` kullanabilirsiniz. ::: ```text "@packages/functions/src/api/index.ts" How is auth handled in @packages/functions/src/api/index.ts? ``` -Dosya icerigi otomatik olarak konusmaya eklenir. +Dosya içeriği otomatik olarak konuşmaya eklenir. --- -## Bash komutlari +## Bash komutları -Bir mesaji `!` ile baslatarak shell komutu calistirin. +Bir mesajı `!` ile başlatarak shell komutu çalıştırın. ```bash frame="none" !ls -la ``` -Komut ciktiisi bir arac sonucu olarak konusmaya eklenir. +Komut çıktısı bir araç sonucu olarak konuşmaya eklenir. --- ## Komutlar -opencode TUI kullanirken `/` ve komut adini yazarak hizli eylemler calistirabilirsiniz. Ornek: +OpenCode TUI kullanırken `/` ve ardından komut adını yazarak hızlı eylemler çalıştırabilirsiniz. Örneğin: ```bash frame="none" /help ``` -Komutlarin cogu, lider tusu `ctrl+x` olan bir kisayola da sahiptir. [Daha fazla bilgi](/docs/keybinds). +Komutların çoğu, lider tuşu `ctrl+x` olan bir kısayola da sahiptir. [Daha fazla bilgi](/docs/keybinds). -Mevcut slash komutlarinin tam listesi: +İşte mevcut slash komutlarının tümü: --- ### connect -opencode'a bir provider ekler. Mevcut provider'lari secip API anahtarlari eklemenizi saglar. +OpenCode'a bir sağlayıcı ekler. Mevcut sağlayıcıları seçip API anahtarları eklemenizi sağlar. ```bash frame="none" /connect @@ -81,172 +81,172 @@ opencode'a bir provider ekler. Mevcut provider'lari secip API anahtarlari ekleme ### compact -Guncel oturumu sikistirir. _Takma ad_: `/summarize` +Mevcut oturumu sıkıştırır. _Takma ad_: `/summarize` ```bash frame="none" /compact ``` -**Kisayol:** `ctrl+x c` +**Kısayol:** `ctrl+x c` --- ### details -Arac calistirma detaylarini goster/gizle yapar. +Araç çalıştırma detaylarını göster/gizle yapar. ```bash frame="none" /details ``` -**Kisayol:** `ctrl+x d` +**Kısayol:** `ctrl+x d` --- ### editor -Mesaj yazmak icin harici editor acar. `EDITOR` ortam degiskeninde ayarli editoru kullanir. [Daha fazla bilgi](#editor-setup). +Mesaj yazmak için harici editör açar. `EDITOR` ortam değişkeninde ayarlı editörü kullanır. [Daha fazla bilgi](#editor-setup). ```bash frame="none" /editor ``` -**Kisayol:** `ctrl+x e` +**Kısayol:** `ctrl+x e` --- ### exit -opencode'dan cikar. _Takma adlar_: `/quit`, `/q` +OpenCode'dan çıkar. _Takma adlar_: `/quit`, `/q` ```bash frame="none" /exit ``` -**Kisayol:** `ctrl+x q` +**Kısayol:** `ctrl+x q` --- ### export -Mevcut konusmayi Markdown olarak disa aktarir ve varsayilan editorunuzde acar. `EDITOR` ortam degiskenindeki editoru kullanir. [Daha fazla bilgi](#editor-setup). +Mevcut konuşmayı Markdown olarak dışa aktarır ve varsayılan editörünüzde açar. `EDITOR` ortam değişkeninde ayarlı editörü kullanır. [Daha fazla bilgi](#editor-setup). ```bash frame="none" /export ``` -**Kisayol:** `ctrl+x x` +**Kısayol:** `ctrl+x x` --- ### help -Yardim penceresini gosterir. +Yardım penceresini gösterir. ```bash frame="none" /help ``` -**Kisayol:** `ctrl+x h` +**Kısayol:** `ctrl+x h` --- ### init -`AGENTS.md` dosyasini olusturur veya gunceller. [Daha fazla bilgi](/docs/rules). +`AGENTS.md` dosyasını oluşturur veya günceller. [Daha fazla bilgi](/docs/rules). ```bash frame="none" /init ``` -**Kisayol:** `ctrl+x i` +**Kısayol:** `ctrl+x i` --- ### models -Kullanilabilir modelleri listeler. +Kullanılabilir modelleri listeler. ```bash frame="none" /models ``` -**Kisayol:** `ctrl+x m` +**Kısayol:** `ctrl+x m` --- ### new -Yeni bir oturum baslatir. _Takma ad_: `/clear` +Yeni bir oturum başlatır. _Takma ad_: `/clear` ```bash frame="none" /new ``` -**Kisayol:** `ctrl+x n` +**Kısayol:** `ctrl+x n` --- ### redo -Geri alinan bir mesaji tekrar uygular. Yalnizca `/undo` kullanildiktan sonra kullanilabilir. +Geri alınan bir mesajı tekrar uygular. Yalnızca `/undo` kullanıldıktan sonra kullanılabilir. :::tip -Dosya degisiklikleri de geri yuklenir. +Herhangi bir dosya değişikliği de geri yüklenir. ::: -Dahilde bu islem dosya degisikliklerini yonetmek icin Git kullanir. Bu nedenle projenizin **bir Git deposu olmasi gerekir**. +Dahili olarak bu işlem dosya değişikliklerini yönetmek için Git kullanır. Bu nedenle projenizin **bir Git deposu olması gerekir**. ```bash frame="none" /redo ``` -**Kisayol:** `ctrl+x r` +**Kısayol:** `ctrl+x r` --- ### sessions -Oturumlari listeler ve aralarinda gecis yapar. _Takma adlar_: `/resume`, `/continue` +Oturumları listeler ve aralarında geçiş yapar. _Takma adlar_: `/resume`, `/continue` ```bash frame="none" /sessions ``` -**Kisayol:** `ctrl+x l` +**Kısayol:** `ctrl+x l` --- ### share -Mevcut oturumu paylasir. [Daha fazla bilgi](/docs/share). +Mevcut oturumu paylaşır. [Daha fazla bilgi](/docs/share). ```bash frame="none" /share ``` -**Kisayol:** `ctrl+x s` +**Kısayol:** `ctrl+x s` --- ### themes -Kullanilabilir temalari listeler. +Kullanılabilir temaları listeler. ```bash frame="none" -/theme +/themes ``` -**Kisayol:** `ctrl+x t` +**Kısayol:** `ctrl+x t` --- ### thinking -Konusmadaki thinking/reasoning bloklarinin gorunurlugunu degistirir. Etkin oldugunda, genisletilmis dusunmeyi destekleyen modellerin akil yurutmelerini gorebilirsiniz. +Konuşmadaki thinking/reasoning bloklarının görünürlüğünü değiştirir. Etkin olduğunda, genişletilmiş düşünmeyi destekleyen modellerin akıl yürütme sürecini görebilirsiniz. :::note -Bu komut sadece thinking bloklarinin **gosterimini** kontrol eder, modelin gercek akil yurutmelerini acip kapatmaz. Gercek akil yurutme yetenegini degistirmek icin `ctrl+t` ile model varyantlari arasinda gecis yapin. +Bu komut sadece thinking bloklarının **gösterilip gösterilmeyeceğini** kontrol eder - modelin akıl yürütme yeteneklerini etkinleştirmez veya devre dışı bırakmaz. Gerçek akıl yürütme yeteneklerini değiştirmek için `ctrl+t` kullanarak model varyantları arasında geçiş yapın. ::: ```bash frame="none" @@ -257,25 +257,25 @@ Bu komut sadece thinking bloklarinin **gosterimini** kontrol eder, modelin gerce ### undo -Konusmadaki son mesaji geri alir. En son kullanici mesaji, sonraki tum yanitlar ve dosya degisiklikleri kaldirilir. +Konuşmadaki son mesajı geri alır. En son kullanıcı mesajını, sonraki tüm yanıtları ve dosya değişikliklerini kaldırır. :::tip -Yapilan dosya degisiklikleri de geri cevrilir. +Yapılan tüm dosya değişiklikleri de geri alınır. ::: -Dahilde bu islem dosya degisikliklerini yonetmek icin Git kullanir. Bu nedenle projenizin **bir Git deposu olmasi gerekir**. +Dahili olarak bu işlem dosya değişikliklerini yönetmek için Git kullanır. Bu nedenle projenizin **bir Git deposu olması gerekir**. ```bash frame="none" /undo ``` -**Kisayol:** `ctrl+x u` +**Kısayol:** `ctrl+x u` --- ### unshare -Mevcut oturumun paylasimini kaldirir. [Daha fazla bilgi](/docs/share#paylasimi-kaldirma). +Mevcut oturumun paylaşımını kaldırır. [Daha fazla bilgi](/docs/share#un-sharing). ```bash frame="none" /unshare @@ -283,9 +283,9 @@ Mevcut oturumun paylasimini kaldirir. [Daha fazla bilgi](/docs/share#paylasimi-k --- -## Editor kurulumu +## Editör kurulumu -`/editor` ve `/export` komutlari, `EDITOR` ortam degiskeninde tanimli editoru kullanir. +Hem `/editor` hem de `/export` komutları, `EDITOR` ortam değişkeninde belirtilen editörü kullanır. @@ -299,7 +299,7 @@ Mevcut oturumun paylasimini kaldirir. [Daha fazla bilgi](/docs/share#paylasimi-k export EDITOR="code --wait" ``` - Kalici yapmak icin bunu kabuk profilinize ekleyin: + Kalıcı yapmak için bunu kabuk profilinize ekleyin; `~/.bashrc`, `~/.zshrc` vb. @@ -313,7 +313,8 @@ Mevcut oturumun paylasimini kaldirir. [Daha fazla bilgi](/docs/share#paylasimi-k set EDITOR=code --wait ``` - Kalici yapmak icin **System Properties** > **Environment Variables** yolunu kullanin. + Kalıcı yapmak için **System Properties** > **Environment + Variables** yolunu kullanın. @@ -326,62 +327,72 @@ Mevcut oturumun paylasimini kaldirir. [Daha fazla bilgi](/docs/share#paylasimi-k $env:EDITOR = "code --wait" ``` - Kalici yapmak icin bunu PowerShell profilinize ekleyin. + Kalıcı yapmak için bunu PowerShell profilinize ekleyin. -Yaygin editor secenekleri: +Popüler editör seçenekleri şunları içerir: - `code` - Visual Studio Code - `cursor` - Cursor - `windsurf` - Windsurf -- `nvim` - Neovim editoru -- `vim` - Vim editoru -- `nano` - Nano editoru +- `nvim` - Neovim editörü +- `vim` - Vim editörü +- `nano` - Nano editörü - `notepad` - Windows Notepad - `subl` - Sublime Text :::note -VS Code gibi bazi editorlerin `--wait` parametresiyle baslatilmasi gerekir. +VS Code gibi bazı editörlerin `--wait` bayrağı ile başlatılması gerekir. ::: -Bazi editorler bloklayici modda calismak icin komut satiri argumanlari ister. `--wait` bayragi editor surecinin kapanana kadar beklemesini saglar. +Bazı editörler bloklama modunda çalışmak için komut satırı argümanlarına ihtiyaç duyar. `--wait` bayrağı, editör süreci kapanana kadar işlemin bloklanmasını sağlar. --- -## Yapilandirin +## Yapılandırma -TUI davranisini opencode config dosyanizdan ozellestirebilirsiniz. +TUI davranışını `tui.json` (veya `tui.jsonc`) aracılığıyla özelleştirebilirsiniz. -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` -### Secenekler +Bu, sunucu/çalışma zamanı davranışını yapılandıran `opencode.json` dosyasından ayrıdır. -- `scroll_acceleration` - Daha akici ve dogal kaydirma icin macOS tarzı hizlanmayi acar. Etkin oldugunda hizli kaydirma hareketlerinde hiz artar, yavas hareketlerde hassas kalir. **Bu ayar etkin oldugunda `scroll_speed` degerini gecersiz kilar.** -- `scroll_speed` - Kaydirma komutlariyla TUI'nin ne kadar hizli kayacagini belirler (minimum: `1`). Varsayilan `3` degeridir. **Not: `scroll_acceleration.enabled` `true` ise yok sayilir.** +### Seçenekler + +- `theme` - UI temanızı ayarlar. [Daha fazla bilgi](/docs/themes). +- `keybinds` - Klavye kısayollarını özelleştirir. [Daha fazla bilgi](/docs/keybinds). +- `scroll_acceleration.enabled` - Pürüzsüz, doğal kaydırma için macOS tarzı kaydırma ivmesini etkinleştirin. Etkinleştirildiğinde, kaydırma hızı hızlı kaydırma hareketleriyle artar ve daha yavaş hareketler için hassas kalır. **Bu ayar `scroll_speed` ayarından önceliklidir ve etkinleştirildiğinde onu geçersiz kılar.** +- `scroll_speed` - Kaydırma komutlarını kullanırken TUI'nin ne kadar hızlı kaydırılacağını kontrol eder (minimum: `0.001`, ondalık değerleri destekler). Varsayılan değer `3`'tür. **Not: `scroll_acceleration.enabled` `true` olarak ayarlanmışsa bu yok sayılır.** +- `diff_style` - Fark (diff) oluşturmayı kontrol eder. `"auto"` terminal genişliğine uyum sağlar, `"stacked"` her zaman tek sütunlu bir düzen gösterir. + +Özel bir TUI yapılandırma yolu yüklemek için `OPENCODE_TUI_CONFIG` kullanın. --- -## Ozellestirme +## Özelleştirme -TUI gorunumunun cesitli kisimlarini komut paletiyle (`ctrl+x h` veya `/help`) ozellestirebilirsiniz. Bu ayarlar yeniden baslatmalar arasinda korunur. +Komut paletini (`ctrl+x h` veya `/help`) kullanarak TUI görünümünün çeşitli yönlerini özelleştirebilirsiniz. Bu ayarlar yeniden başlatmalar arasında korunur. --- -#### Kullanici adi gorunumu +#### Kullanıcı adı görünümü -Sohbet mesajlarinda kullanici adinizin gosterilip gosterilmeyecegini degistirir. Sunlardan erisebilirsiniz: +Sohbet mesajlarında kullanıcı adınızın görünüp görünmeyeceğini değiştirin. Buna şuradan erişin: -- Komut paleti: "username" veya "hide username" aratin -- Ayar otomatik saklanir ve TUI oturumlarinda hatirlanir +- Komut paleti: "username" veya "hide username" araması yapın +- Ayar otomatik olarak kalıcı hale gelir ve TUI oturumları arasında hatırlanır diff --git a/packages/web/src/content/docs/tr/zen.mdx b/packages/web/src/content/docs/tr/zen.mdx index b997889419..9582a7b7dc 100644 --- a/packages/web/src/content/docs/tr/zen.mdx +++ b/packages/web/src/content/docs/tr/zen.mdx @@ -1,61 +1,61 @@ --- title: Zen -description: opencode ekibinin sundugu secili model listesi. +description: opencode tarafından sağlanan seçilmiş modeller listesi. --- import config from "../../../../config.mjs" export const console = config.console export const email = `mailto:${config.email}` -OpenCode Zen, opencode ekibi tarafindan test edilip dogrulanmis modellerin listesidir. +OpenCode Zen, opencode ekibi tarafından test edilip doğrulanmış modellerin bir listesidir. :::note -OpenCode Zen su anda beta asamasindadir. +OpenCode Zen şu anda beta aşamasındadır. ::: -Zen, opencode'daki diger provider'lar gibi calisir. OpenCode Zen'e giris yapar ve API anahtarinizi alirsiniz. -Tamamen istege baglidir; opencode kullanmak icin Zen kullanmak zorunda degilsiniz. +Zen, opencode'daki diğer sağlayıcılar gibi çalışır. OpenCode Zen'e giriş yapar ve API anahtarınızı alırsınız. Tamamen isteğe bağlıdır ve opencode kullanmak için bunu kullanmanıza gerek yoktur. --- ## Arka plan -Piyasada cok sayida model var, ancak bunlarin sadece bir kismi kodlama ajani olarak iyi calisir. Ayrica provider'larin cogu birbirinden cok farkli sekilde ayarlanir; bu da performans ve kaliteyi ciddi bicimde degistirir. +Piyasada çok sayıda model var ancak bu modellerden sadece birkaçı kodlama ajanı olarak iyi çalışır. Ayrıca çoğu sağlayıcı çok farklı şekilde yapılandırılmıştır; bu nedenle çok farklı performans ve kalite elde edersiniz. :::tip -opencode ile iyi calisan belirli model/provider kombinasyonlarini test ettik. +opencode ile iyi çalışan seçkin bir grup model ve sağlayıcıyı test ettik. ::: -Bu nedenle OpenRouter benzeri bir servis uzerinden model kullaniyorsaniz, istediginiz modelin en iyi surumunu alip almadiginizdan her zaman emin olamazsiniz. +Bu nedenle, OpenRouter gibi bir şey üzerinden bir model kullanıyorsanız, istediğiniz modelin en iyi sürümünü alıp almadığınızdan asla emin olamazsınız. -Bunu cozmeye yonelik olarak sunlari yaptik: +Bunu düzeltmek için birkaç şey yaptık: -1. Secili bir model grubunu test ettik ve ekipleriyle en iyi calisma sekli uzerine gorustuk -2. Daha sonra bazi provider'larla bu modellerin dogru sekilde sunuldugunu dogruladik -3. Son olarak model/provider kombinasyonlarini benchmark ederek guvenle onerebilecegimiz bir liste olusturduk +1. Seçkin bir grup modeli test ettik ve ekipleriyle bunları en iyi nasıl çalıştıracakları hakkında konuştuk. +2. Daha sonra bunların doğru şekilde sunulduğundan emin olmak için birkaç sağlayıcıyla çalıştık. +3. Son olarak model/sağlayıcı kombinasyonunu karşılaştırdık ve önermekten memnuniyet duyduğumuz bir liste oluşturduk. -OpenCode Zen, bu modellere erisim saglayan bir AI gateway'dir. +OpenCode Zen, bu modellere erişmenizi sağlayan bir AI ağ geçididir. --- -## Nasil calisir +## Nasıl çalışır -OpenCode Zen, opencode'daki diger provider'lar gibi calisir. +OpenCode Zen, opencode'daki diğer sağlayıcılar gibi çalışır. -1. **OpenCode Zen** hesabina giris yapin, odeme bilgilerinizi ekleyin ve API anahtarinizi kopyalayin -2. TUI'da `/connect` komutunu calistirin, OpenCode Zen'i secin ve API anahtarinizi yapistirin -3. Onerdigimiz model listesini gormek icin TUI'da `/models` calistirin +1. **OpenCode Zen**'de oturum açın, fatura ayrıntılarınızı ekleyin ve API anahtarınızı kopyalayın. +2. TUI'de `/connect` komutunu çalıştırın, OpenCode Zen'i seçin ve API anahtarınızı yapıştırın. +3. Önerdiğimiz modellerin listesini görmek için TUI'de `/models` komutunu çalıştırın. -Ucretlendirme istek basina yapilir ve hesabiniza kredi yukleyebilirsiniz. +İstek başına ücretlendirilirsiniz ve hesabınıza kredi ekleyebilirsiniz. --- -## Endpoint'ler +## Uç Noktalar -Modellerimize asagidaki API endpoint'leri uzerinden de erisebilirsiniz. +Modellerimize aşağıdaki API uç noktaları aracılığıyla da erişebilirsiniz. | Model | Model ID | Endpoint | AI SDK Package | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -65,35 +65,36 @@ Modellerimize asagidaki API endpoint'leri uzerinden de erisebilirsiniz. | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Big Pickle | big-pickle | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -opencode config'inizdeki [model id](/docs/config/#models), `opencode/` formatini kullanir. -Ornegin GPT 5.2 Codex icin config'te `opencode/gpt-5.2-codex` kullanirsiniz. +opencode yapılandırmanızdaki [model kimliği](/docs/config/#models) `opencode/` biçimini kullanır. Örneğin, GPT 5.2 Codex için yapılandırmanızda `opencode/gpt-5.2-codex` kullanırsınız. --- ### Modeller -Mevcut modellerin tam listesini ve metadatasini su adresten cekebilirsiniz: +Mevcut modellerin tam listesini ve meta verilerini şuradan alabilirsiniz: ``` https://opencode.ai/zen/v1/models @@ -101,36 +102,41 @@ https://opencode.ai/zen/v1/models --- -## Fiyatlandirma +## Fiyatlandırma -Kullandikca ode modelini destekliyoruz. Asagidaki fiyatlar **1M token basina** verilmistir. +Kullandıkça öde modelini destekliyoruz. Aşağıda **1 milyon token başına** fiyatlar verilmiştir. | Model | Input | Output | Cached Read | Cached Write | | --------------------------------- | ------ | ------ | ----------- | ------------ | | Big Pickle | Free | Free | Free | - | -| MiniMax M2.1 Free | Free | Free | Free | - | +| MiniMax M2.5 Free | Free | Free | Free | - | +| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | - | | MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | -| GLM 4.7 Free | Free | Free | Free | - | +| GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 Free | Free | Free | Free | - | | Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - | +| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Claude Sonnet 4.6 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.6 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4.5 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | -| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Gemini 3.1 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3.1 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - | @@ -141,98 +147,94 @@ Kullandikca ode modelini destekliyoruz. Asagidaki fiyatlar **1M token basina** v | GPT 5 Codex | $1.07 | $8.50 | $0.107 | - | | GPT 5 Nano | Free | Free | Free | - | -Kullanim gecmisinizde _Claude Haiku 3.5_ gorebilirsiniz. Bu, oturum basliklarini olusturmak icin kullanilan [dusuk maliyetli bir modeldir](/docs/config/#models). +Kullanım geçmişinizde _Claude Haiku 3.5_ fark edebilirsiniz. Bu, oturumlarınızın başlıklarını oluşturmak için kullanılan [düşük maliyetli bir modeldir](/docs/config/#models). :::note -Kredi karti ucretleri maliyetine yansitilir (islem basina %4.4 + $0.30); bunun disinda ek ucret almiyoruz. +Kredi kartı ücretleri maliyetine yansıtılır (işlem başına %4,4 + 0,30$); bunun ötesinde hiçbir ücret talep etmiyoruz. ::: -Ucretsiz modeller: +Ücretsiz modeller: -- GLM 4.7 Free, sinirli bir sure icin opencode'da ucretsizdir. Ekip bu surede geri bildirim toplayip modeli iyilestiriyor -- Kimi K2.5 Free, sinirli bir sure icin opencode'da ucretsizdir. Ekip bu surede geri bildirim toplayip modeli iyilestiriyor -- MiniMax M2.1 Free, sinirli bir sure icin opencode'da ucretsizdir. Ekip bu surede geri bildirim toplayip modeli iyilestiriyor -- Big Pickle, sinirli bir sure icin opencode'da ucretsiz olan gizli bir modeldir. Ekip bu surede geri bildirim toplayip modeli iyilestiriyor +- MiniMax M2.5 Free, sınırlı bir süre için OpenCode'da ücretsizdir. Ekip bu süreyi geri bildirim toplamak ve modeli iyileştirmek için kullanıyor. +- Big Pickle, sınırlı bir süre için OpenCode'da ücretsiz olan gizli bir modeldir. Ekip bu süreyi geri bildirim toplamak ve modeli iyileştirmek için kullanıyor. -Sorunuz varsa bize ulasin. +Sorularınız varsa bizimle iletişime geçin. --- -### Otomatik yukleme +### Otomatik yükleme -Bakiyeniz $5'in altina dustugunde Zen otomatik olarak $20 yukler. +Bakiyeniz 5$'ın altına düşerse, Zen otomatik olarak 20$ yükler. -Otomatik yukleme tutarini degistirebilir veya bu ozelligi tamamen kapatabilirsiniz. +Otomatik yükleme tutarını değiştirebilirsiniz. Otomatik yüklemeyi tamamen devre dışı da bırakabilirsiniz. --- -### Aylik limitler +### Aylık limitler -Tum calisma alani ve ekip uyeleri icin aylik kullanim limiti belirleyebilirsiniz. +Ayrıca tüm çalışma alanı ve ekibinizin her üyesi için aylık kullanım limiti belirleyebilirsiniz. -Ornegin aylik limiti $20 yaptiysaniz Zen bir ayda $20'den fazla kullandirtmaz. Ancak otomatik yukleme aciksa bakiye $5 altina dustugunde toplam odemeniz $20'nin uzerine cikabilir. +Örneğin, aylık kullanım limitini 20$ olarak ayarladığınızı varsayalım, Zen bir ayda 20$'dan fazla kullanmaz. Ancak otomatik yüklemeyi etkinleştirdiyseniz, bakiyeniz 5$'ın altına düşerse Zen sizden 20$'dan fazla ücret alabilir. --- ## Gizlilik -Tum modellerimiz ABD'de barindiriliyor. Provider'larimiz sifir saklama politikasini izler ve verilerinizi model egitimi icin kullanmaz; asagidaki istisnalar haric: +Tüm modellerimiz ABD'de barındırılmaktadır. Sağlayıcılarımız sıfır saklama politikasını izler ve aşağıdaki istisnalar dışında verilerinizi model eğitimi için kullanmaz: -- Big Pickle: Ucretsiz donemde toplanan veriler modeli iyilestirmek icin kullanilabilir -- GLM 4.7 Free: Ucretsiz donemde toplanan veriler modeli iyilestirmek icin kullanilabilir -- Kimi K2.5 Free: Ucretsiz donemde toplanan veriler modeli iyilestirmek icin kullanilabilir -- MiniMax M2.1 Free: Ucretsiz donemde toplanan veriler modeli iyilestirmek icin kullanilabilir -- OpenAI API'leri: Istekler [OpenAI veri politikalari](https://platform.openai.com/docs/guides/your-data) kapsaminda 30 gun saklanir -- Anthropic API'leri: Istekler [Anthropic veri politikalari](https://docs.anthropic.com/en/docs/claude-code/data-usage) kapsaminda 30 gun saklanir +- Big Pickle: Ücretsiz döneminde toplanan veriler modeli iyileştirmek için kullanılabilir. +- MiniMax M2.5 Free: Ücretsiz döneminde toplanan veriler modeli iyileştirmek için kullanılabilir. +- OpenAI API'leri: İstekler [OpenAI'nin Veri Politikaları](https://platform.openai.com/docs/guides/your-data) uyarınca 30 gün boyunca saklanır. +- Anthropic API'leri: İstekler [Anthropic'in Veri Politikaları](https://docs.anthropic.com/en/docs/claude-code/data-usage) uyarınca 30 gün boyunca saklanır. --- -## Ekipler icin +## Ekipler İçin -Zen ekipler icin de guclu bir cozumdur. Ekip arkadaslarini davet edebilir, roller atayabilir, kullanilacak modelleri yonetebilir ve daha fazlasini yapabilirsiniz. +Zen ekipler için de harika çalışır. Ekip arkadaşlarınızı davet edebilir, roller atayabilir, ekibinizin kullandığı modelleri düzenleyebilir ve daha fazlasını yapabilirsiniz. :::note -Calisma alanlari beta kapsaminda su anda ekipler icin ucretsizdir. +Çalışma alanları şu anda beta'nın bir parçası olarak ekipler için ücretsizdir. ::: -Calisma alani yonetimi su anda beta kapsaminda ucretsizdir. Fiyatlandirma detaylarini yakinda paylasacagiz. +Çalışma alanınızı yönetmek şu anda beta'nın bir parçası olarak ekipler için ücretsizdir. Yakında fiyatlandırma hakkında daha fazla ayrıntı paylaşacağız. --- ### Roller -Calisma alaniniza ekip arkadaslarini davet edip rol atayabilirsiniz: +Ekip arkadaşlarınızı çalışma alanınıza davet edebilir ve roller atayabilirsiniz: -- **Admin**: Modelleri, uyeleri, API anahtarlarini ve faturalandirmayi yonetir -- **Member**: Yalnizca kendi API anahtarlarini yonetir +- **Admin**: Modelleri, üyeleri, API anahtarlarını ve faturalandırmayı yönetin +- **Member**: Yalnızca kendi API anahtarlarını yönetin -Admin'ler maliyet kontrolu icin uye bazinda aylik harcama limitleri de ayarlayabilir. +Yöneticiler, maliyetleri kontrol altında tutmak için her üye için aylık harcama limitleri de belirleyebilir. --- -### Model erisimi +### Model erişimi -Admin'ler calisma alani icin belirli modelleri acip kapatabilir. Devre disi bir modele yapilan istekler hata dondurur. +Yöneticiler çalışma alanı için belirli modelleri etkinleştirebilir veya devre dışı bırakabilir. Devre dışı bırakılmış bir modele yapılan istekler bir hata döndürür. -Bu, veri toplayan bir modelin kullanimini kapatmak istediginiz durumlarda kullanislidir. +Bu, veri toplayan bir modelin kullanımını devre dışı bırakmak istediğiniz durumlarda kullanışlıdır. --- -### Kendi anahtarinizi kullanin +### Kendi anahtarınızı getirin -Zen'deki diger modellere erisirken kendi OpenAI veya Anthropic API anahtarlarinizi da kullanabilirsiniz. +Zen'deki diğer modellere erişmeye devam ederken kendi OpenAI veya Anthropic API anahtarlarınızı kullanabilirsiniz. -Kendi anahtarinizi kullandiginizda token ucreti Zen yerine dogrudan provider tarafindan faturalandirilir. +Kendi anahtarlarınızı kullandığınızda, tokenler Zen tarafından değil, doğrudan sağlayıcı tarafından faturalandırılır. -Ornegin kurulusunuzun zaten OpenAI veya Anthropic anahtari varsa Zen'in sagladigi anahtar yerine onu kullanabilirsiniz. +Örneğin, kuruluşunuzun halihazırda OpenAI veya Anthropic için bir anahtarı olabilir ve Zen'in sağladığı anahtar yerine onu kullanmak isteyebilirsiniz. --- ## Hedefler -OpenCode Zen'i su amaclarla olusturduk: +OpenCode Zen'i şu amaçlarla oluşturduk: -1. Kodlama ajanlari icin en iyi model/provider kombinasyonlarini **benchmark etmek** -2. Performansi dusurmeden veya daha ucuz provider'a yonlendirmeden **en yuksek kaliteye** erismek -3. Maliyetine satarak fiyat dususlerini kullaniciya yansitmak ve yalnizca islem ucretlerini kapsayan pay birakmak -4. Herhangi bir kodlama ajaniyla kullanima izin vererek **kilitlenmeyi onlemek** ve opencode'da diger provider'lari her zaman acik tutmak +1. Kodlama ajanları için en iyi modelleri/sağlayıcıları **kıyaslamak**. +2. **En yüksek kaliteli** seçeneklere erişmek ve performansı düşürmemek veya daha ucuz sağlayıcılara yönlendirmemek. +3. Maliyetine satış yaparak herhangi bir **fiyat düşüşünü** yansıtmak; böylece tek kâr marjı işlem ücretlerimizi karşılamaktır. +4. Başka bir kodlama ajanıyla kullanmanıza izin vererek **kilitlenmeyi önlemek**. Ve her zaman OpenCode ile başka bir sağlayıcıyı kullanmanıza izin vermek. diff --git a/packages/web/src/content/docs/zen.mdx b/packages/web/src/content/docs/zen.mdx index 48c040cf2d..5ed2125cb1 100644 --- a/packages/web/src/content/docs/zen.mdx +++ b/packages/web/src/content/docs/zen.mdx @@ -121,12 +121,12 @@ We support a pay-as-you-go model. Below are the prices **per 1M tokens**. | --------------------------------- | ------ | ------ | ----------- | ------------ | | Big Pickle | Free | Free | Free | - | | MiniMax M2.5 Free | Free | Free | Free | - | -| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | - | +| MiniMax M2.5 | $0.30 | $1.20 | $0.06 | $0.375 | | MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | | GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - | @@ -192,6 +192,19 @@ charging you more than $20 if your balance goes below $5. --- +### Deprecated models + +| Model | Deprecation date | +| ---------------- | ---------------- | +| Qwen3 Coder 480B | Feb 6, 2026 | +| Kimi K2 Thinking | March 6, 2026 | +| Kimi K2 | March 6, 2026 | +| MiniMax M2.1 | March 15, 2026 | +| GLM 4.7 | March 15, 2026 | +| GLM 4.6 | March 15, 2026 | + +--- + ## Privacy All our models are hosted in the US. Our providers follow a zero-retention policy and do not use your data for model training, with the following exceptions: diff --git a/packages/web/src/content/docs/zh-cn/cli.mdx b/packages/web/src/content/docs/zh-cn/cli.mdx index 490d59ca0b..503207ec48 100644 --- a/packages/web/src/content/docs/zh-cn/cli.mdx +++ b/packages/web/src/content/docs/zh-cn/cli.mdx @@ -558,6 +558,7 @@ OpenCode 可以通过环境变量进行配置。 | `OPENCODE_AUTO_SHARE` | boolean | 自动分享会话 | | `OPENCODE_GIT_BASH_PATH` | string | Windows 上 Git Bash 可执行文件的路径 | | `OPENCODE_CONFIG` | string | 配置文件路径 | +| `OPENCODE_TUI_CONFIG` | string | TUI 配置文件路径 | | `OPENCODE_CONFIG_DIR` | string | 配置目录路径 | | `OPENCODE_CONFIG_CONTENT` | string | 内联 JSON 配置内容 | | `OPENCODE_DISABLE_AUTOUPDATE` | boolean | 禁用自动更新检查 | diff --git a/packages/web/src/content/docs/zh-cn/config.mdx b/packages/web/src/content/docs/zh-cn/config.mdx index 8ed3c8fbee..c401bcf121 100644 --- a/packages/web/src/content/docs/zh-cn/config.mdx +++ b/packages/web/src/content/docs/zh-cn/config.mdx @@ -14,10 +14,11 @@ OpenCode 支持 **JSON** 和 **JSONC**(带注释的 JSON)格式。 ```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", - // Theme configuration - "theme": "opencode", "model": "anthropic/claude-sonnet-4-5", "autoupdate": true, + "server": { + "port": 4096, + }, } ``` @@ -33,7 +34,7 @@ OpenCode 支持 **JSON** 和 **JSONC**(带注释的 JSON)格式。 配置文件是合并在一起的,而不是被替换。来自以下配置位置的设置会被合并。后面的配置仅在键冲突时覆盖前面的配置。所有配置中的非冲突设置都会被保留。 -例如,如果您的全局配置设置了 `theme: "opencode"` 和 `autoupdate: true`,而您的项目配置设置了 `model: "anthropic/claude-sonnet-4-5"`,则最终配置将包含所有三个设置。 +例如,如果您的全局配置设置了 `autoupdate: true`,而您的项目配置设置了 `model: "anthropic/claude-sonnet-4-5"`,则最终配置将包含这两个设置。 --- diff --git a/packages/web/src/content/docs/zh-cn/go.mdx b/packages/web/src/content/docs/zh-cn/go.mdx new file mode 100644 index 0000000000..8bd32a8ad4 --- /dev/null +++ b/packages/web/src/content/docs/zh-cn/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: 低成本的开源编程模型订阅服务。 +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go 是一项低成本的订阅服务(**$10/月**),为您提供对流行开源编程模型的可靠访问。 + +:::note +OpenCode Go 目前处于测试阶段。 +::: + +Go 的工作方式与 OpenCode 中的其他提供商一样。您订阅 OpenCode Go 并获取 API 密钥。这是**完全可选的**,您不需要它也能使用 OpenCode。 + +它主要为国际用户设计,模型托管在美国、欧盟和新加坡,以确保稳定的全球访问。 + +--- + +## 背景 + +开源模型已经变得非常出色。它们现在在编程任务上的表现接近专有模型。而且因为许多提供商可以竞争性地提供服务,它们通常要便宜得多。 + +然而,获得可靠、低延迟的访问可能很困难。提供商的质量和可用性各不相同。 + +:::tip +我们测试了一组精选的模型和提供商,它们与 OpenCode 配合良好。 +::: + +为了解决这个问题,我们做了一些事情: + +1. 我们测试了一组精选的开源模型,并与他们的团队讨论了如何最好地运行它们。 +2. 然后,我们与几家提供商合作,确保这些模型得到正确的服务。 +3. 最后,我们对模型/提供商的组合进行了基准测试,并得出了一个我们乐于推荐的列表。 + +OpenCode Go 让您可以以 **$10/月** 的价格访问这些模型。 + +--- + +## 工作原理 + +OpenCode Go 的工作方式与 OpenCode 中的其他提供商一样。 + +1. 登录 **OpenCode Zen**,订阅 Go,并复制您的 API 密钥。 +2. 在 TUI 中运行 `/connect` 命令,选择 `OpenCode Go`,然后粘贴您的 API 密钥。 +3. 在 TUI 中运行 `/models` 以查看通过 Go 可用的模型列表。 + +:::note +每个工作区只有一名成员可以订阅 OpenCode Go。 +::: + +目前的模型列表包括: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +随着我们测试和添加新模型,模型列表可能会发生变化。 + +--- + +## 使用限制 + +OpenCode Go 包含以下限制: + +- **5 小时限制** — $12 的使用量 +- **每周限制** — $30 的使用量 +- **每月限制** — $60 的使用量 + +限制是以美元价值定义的。这意味着您的实际请求数量取决于您使用的模型。像 MiniMax M2.5 这样更便宜的模型允许更多的请求,而像 GLM-5 这样成本更高的模型允许的请求较少。 + +下表提供了基于典型 Go 使用模式的估计请求数: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| --------------- | ----- | --------- | ------------ | +| 每 5 小时请求数 | 1,150 | 1,850 | 30,000 | +| 每周请求数 | 2,880 | 4,630 | 75,000 | +| 每月请求数 | 5,750 | 9,250 | 150,000 | + +估计值基于观察到的平均请求模式: + +- GLM-5 — 每次请求 700 输入,52,000 缓存,150 输出 token +- Kimi K2.5 — 每次请求 870 输入,55,000 缓存,200 输出 token +- MiniMax M2.5 — 每次请求 300 输入,55,000 缓存,125 输出 token + +您可以在 **console** 中跟踪当前的用量。 + +:::tip +如果您达到使用限制,您可以继续使用免费模型。 +::: + +随着我们从早期使用和反馈中学习,使用限制可能会发生变化。 + +--- + +### 定价 + +OpenCode Go 是一个 **$10/月** 的订阅计划。以下是**每 1M token** 的价格。 + +| Model | Input | Output | Cached Read | +| ------------ | ----- | ------ | ----------- | +| GLM-5 | $1.00 | $3.20 | $0.20 | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | +| MiniMax M2.5 | $0.30 | $1.20 | $0.03 | + +--- + +### 超出限制的使用 + +如果您的 Zen 余额中还有信用点数,您可以在控制台中启用 **Use balance**(使用余额)选项。启用后,当您达到使用限制时,Go 将回退到您的 Zen 余额,而不是阻止请求。 + +--- + +## 端点 + +您也可以通过以下 API 端点访问 Go 模型。 + +| Model | Model ID | Endpoint | AI SDK Package | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +OpenCode 配置中的 [model id](/docs/config/#models) 使用 `opencode-go/` 格式。例如,对于 Kimi K2.5,您将在配置中使用 `opencode-go/kimi-k2.5`。 + +--- + +## 隐私 + +该计划主要为国际用户设计,模型托管在美国、欧盟和新加坡,以确保稳定的全球访问。 + +如有任何问题,请 联系我们。 + +--- + +## 目标 + +我们要创建 OpenCode Go 以: + +1. 通过低成本订阅让更多人**获得** AI 编程能力。 +2. 提供对最佳开源编程模型的**可靠**访问。 +3. 策划经过**测试和基准测试**的、适合编程代理使用的模型。 +4. **无锁定**,允许您在 OpenCode 中使用任何其他提供商。 diff --git a/packages/web/src/content/docs/zh-cn/keybinds.mdx b/packages/web/src/content/docs/zh-cn/keybinds.mdx index bb1d2c21a7..5108fdbb51 100644 --- a/packages/web/src/content/docs/zh-cn/keybinds.mdx +++ b/packages/web/src/content/docs/zh-cn/keybinds.mdx @@ -3,11 +3,11 @@ title: 快捷键 description: 自定义您的快捷键。 --- -OpenCode 提供了一系列快捷键,您可以通过 OpenCode 配置进行自定义。 +OpenCode 提供了一系列快捷键,您可以通过 `tui.json` 进行自定义。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -117,11 +117,11 @@ OpenCode 的大多数快捷键使用 `leader`(前导键)。这可以避免 ## 禁用快捷键 -您可以通过在配置中将对应的键值设置为 "none" 来禁用某个快捷键。 +您可以通过将键值添加到 `tui.json` 并设置为 "none" 来禁用某个快捷键。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/zh-cn/themes.mdx b/packages/web/src/content/docs/zh-cn/themes.mdx index d1abefed6d..79386fbe99 100644 --- a/packages/web/src/content/docs/zh-cn/themes.mdx +++ b/packages/web/src/content/docs/zh-cn/themes.mdx @@ -61,11 +61,11 @@ OpenCode 自带多个内置主题。 ## 使用主题 -您可以通过 `/theme` 命令调出主题选择界面来选择主题,也可以在[配置](/docs/config)文件中直接指定。 +您可以通过 `/theme` 命令调出主题选择界面来选择主题,也可以在 `tui.json` 文件中直接指定。 -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` diff --git a/packages/web/src/content/docs/zh-cn/zen.mdx b/packages/web/src/content/docs/zh-cn/zen.mdx index e3fe35e867..0c6c6b9d95 100644 --- a/packages/web/src/content/docs/zh-cn/zen.mdx +++ b/packages/web/src/content/docs/zh-cn/zen.mdx @@ -55,6 +55,7 @@ OpenCode Zen 的工作方式与 OpenCode 中的任何其他提供商相同。 | 模型 | 模型 ID | 端点 | AI SDK 包 | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -79,11 +80,9 @@ OpenCode Zen 的工作方式与 OpenCode 中的任何其他提供商相同。 | MiniMax M2.5 Free | minimax-m2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 5 | glm-5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| GLM 5 Free | glm-5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -113,11 +112,9 @@ https://opencode.ai/zen/v1/models | MiniMax M2.5 Free | 免费 | 免费 | 免费 | - | | MiniMax M2.5 | $0.30 | $1.20 | $0.06 | - | | MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - | -| GLM 5 Free | Free | Free | Free | - | | GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 Free | 免费 | 免费 | 免费 | - | | Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | @@ -139,6 +136,7 @@ https://opencode.ai/zen/v1/models | Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - | @@ -157,8 +155,6 @@ https://opencode.ai/zen/v1/models 免费模型说明: -- GLM 5 Free 在 OpenCode 上限时免费提供。团队正在利用这段时间收集反馈并改进模型。 -- Kimi K2.5 Free 在 OpenCode 上限时免费提供。团队正在利用这段时间收集反馈并改进模型。 - MiniMax M2.5 Free 在 OpenCode 上限时免费提供。团队正在利用这段时间收集反馈并改进模型。 - Big Pickle 是一个隐身模型,在 OpenCode 上限时免费提供。团队正在利用这段时间收集反馈并改进模型。 @@ -187,8 +183,6 @@ https://opencode.ai/zen/v1/models 我们所有的模型都托管在美国。我们的提供商遵循零保留政策,不会将你的数据用于模型训练,但以下情况除外: - Big Pickle:在免费期间,收集的数据可能会被用于改进模型。 -- GLM 5 Free:在免费期间,收集的数据可能会被用于改进模型。 -- Kimi K2.5 Free:在免费期间,收集的数据可能会被用于改进模型。 - MiniMax M2.5 Free:在免费期间,收集的数据可能会被用于改进模型。 - OpenAI API:请求会根据 [OpenAI 数据政策](https://platform.openai.com/docs/guides/your-data)保留 30 天。 - Anthropic API:请求会根据 [Anthropic 数据政策](https://docs.anthropic.com/en/docs/claude-code/data-usage)保留 30 天。 diff --git a/packages/web/src/content/docs/zh-tw/cli.mdx b/packages/web/src/content/docs/zh-tw/cli.mdx index f11066dcf5..888740f5be 100644 --- a/packages/web/src/content/docs/zh-tw/cli.mdx +++ b/packages/web/src/content/docs/zh-tw/cli.mdx @@ -558,6 +558,7 @@ OpenCode 可以透過環境變數進行設定。 | `OPENCODE_AUTO_SHARE` | boolean | 自動分享工作階段 | | `OPENCODE_GIT_BASH_PATH` | string | Windows 上 Git Bash 可執行檔的路徑 | | `OPENCODE_CONFIG` | string | 設定檔路徑 | +| `OPENCODE_TUI_CONFIG` | string | TUI 設定檔路徑 | | `OPENCODE_CONFIG_DIR` | string | 設定目錄路徑 | | `OPENCODE_CONFIG_CONTENT` | string | 內嵌 JSON 設定內容 | | `OPENCODE_DISABLE_AUTOUPDATE` | boolean | 停用自動更新檢查 | diff --git a/packages/web/src/content/docs/zh-tw/config.mdx b/packages/web/src/content/docs/zh-tw/config.mdx index 3715dd0c9f..a694823a65 100644 --- a/packages/web/src/content/docs/zh-tw/config.mdx +++ b/packages/web/src/content/docs/zh-tw/config.mdx @@ -14,10 +14,11 @@ OpenCode 支援 **JSON** 和 **JSONC**(帶註解的 JSON)格式。 ```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", - // Theme configuration - "theme": "opencode", "model": "anthropic/claude-sonnet-4-5", "autoupdate": true, + "server": { + "port": 4096, + }, } ``` @@ -33,7 +34,7 @@ OpenCode 支援 **JSON** 和 **JSONC**(帶註解的 JSON)格式。 設定檔是合併在一起的,而不是被替換。來自以下設定位置的設定會被合併。後面的設定僅在鍵衝突時覆寫前面的設定。所有設定中的非衝突設定都會被保留。 -例如,如果您的全域設定設定了 `theme: "opencode"` 和 `autoupdate: true`,而您的專案設定設定了 `model: "anthropic/claude-sonnet-4-5"`,則最終設定將包含所有三個設定。 +例如,如果您的全域設定設定了 `autoupdate: true`,而您的專案設定設定了 `model: "anthropic/claude-sonnet-4-5"`,則最終設定將包含這兩個設定。 --- @@ -171,6 +172,10 @@ opencode run "Hello world" - `scroll_speed` - 自訂捲動速度倍率(預設值:`3`,最小值:`1`)。如果 `scroll_acceleration.enabled` 為 `true`,則忽略此選項。 - `diff_style` - 控制差異呈現方式。`"auto"` 根據終端機寬度自適應,`"stacked"` 始終顯示單列。 +使用 `OPENCODE_TUI_CONFIG` 指向自訂 TUI 設定檔。 + +`opencode.json` 中的舊版 `theme`、`keybinds` 和 `tui` 鍵已被棄用,並將在可能的情況下自動遷移。 + [在此了解更多關於 TUI 的資訊](/docs/tui)。 --- @@ -297,12 +302,12 @@ Bearer Token(`AWS_BEARER_TOKEN_BEDROCK` 或 `/connect`)優先於基於設定 ### 主題 -您可以透過 OpenCode 設定中的 `theme` 選項設定要使用的主題。 +在 `tui.json` 中設定您的 UI 主題。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "theme": "" + "$schema": "https://opencode.ai/tui.json", + "theme": "tokyonight" } ``` @@ -402,11 +407,11 @@ Bearer Token(`AWS_BEARER_TOKEN_BEDROCK` 或 `/connect`)優先於基於設定 ### 快捷鍵 -您可以透過 `keybinds` 選項自訂快捷鍵。 +在 `tui.json` 中自訂快捷鍵。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": {} } ``` diff --git a/packages/web/src/content/docs/zh-tw/custom-tools.mdx b/packages/web/src/content/docs/zh-tw/custom-tools.mdx index 3229c6fddf..86c2b0467f 100644 --- a/packages/web/src/content/docs/zh-tw/custom-tools.mdx +++ b/packages/web/src/content/docs/zh-tw/custom-tools.mdx @@ -79,6 +79,32 @@ export const multiply = tool({ --- +#### 與內建工具名稱衝突 + +自訂工具以工具名稱作為鍵值。如果自訂工具使用與內建工具相同的名稱,則自訂工具具有優先權。 + +例如,此檔案將替換內建的 `bash` 工具: + +```ts title=".opencode/tools/bash.ts" +import { tool } from "@opencode-ai/plugin" + +export default tool({ + description: "Restricted bash wrapper", + args: { + command: tool.schema.string(), + }, + async execute(args) { + return `blocked: ${args.command}` + }, +}) +``` + +:::note +除非您有意替換內建工具,否則請使用唯一的名稱。如果您想停用內建工具但不覆寫它,請使用[權限](/docs/permissions)。 +::: + +--- + ### 參數 您可以使用 `tool.schema`(即 [Zod](https://zod.dev))來定義參數型別。 diff --git a/packages/web/src/content/docs/zh-tw/go.mdx b/packages/web/src/content/docs/zh-tw/go.mdx new file mode 100644 index 0000000000..0337a3c385 --- /dev/null +++ b/packages/web/src/content/docs/zh-tw/go.mdx @@ -0,0 +1,145 @@ +--- +title: Go +description: 針對開放原始碼程式設計模型的低成本訂閱服務。 +--- + +import config from "../../../../config.mjs" +export const console = config.console +export const email = `mailto:${config.email}` + +OpenCode Go 是一項低成本的 **每月 10 美元** 訂閱服務,讓您可以穩定存取熱門的開放原始碼程式設計模型。 + +:::note +OpenCode Go 目前處於測試階段 (Beta)。 +::: + +Go 的運作方式就像 OpenCode 中的任何其他供應商一樣。您訂閱 OpenCode Go 並取得您的 API key。這是**完全選用**的,您不需要使用它也能使用 OpenCode。 + +主要是為國際使用者設計,模型託管在美國、歐盟和新加坡,以提供穩定的全球存取。 + +--- + +## 背景 + +開放模型已經變得非常優秀。它們現在在程式設計任務上的表現已接近專有模型。而且因為許多供應商都能以具競爭力的方式提供服務,它們通常便宜得多。 + +然而,要獲得穩定且低延遲的存取可能會很困難。供應商的品質和可用性各不相同。 + +:::tip +我們測試了一組精選的模型和供應商,它們與 OpenCode 搭配運作良好。 +::: + +為了解決這個問題,我們做了幾件事: + +1. 我們測試了一組精選的開放模型,並與他們的團隊討論如何最好地運行它們。 +2. 接著我們與幾家供應商合作,確保這些模型能正確地提供服務。 +3. 最後,我們對模型/供應商的組合進行基準測試,並提出了一份我們覺得值得推薦的清單。 + +OpenCode Go 讓您能以 **每月 10 美元** 的價格存取這些模型。 + +--- + +## 運作方式 + +OpenCode Go 的運作方式就像 OpenCode 中的任何其他供應商一樣。 + +1. 您登入 **OpenCode Zen**,訂閱 Go,並複製您的 API key。 +2. 您在 TUI 中執行 `/connect` 指令,選擇 `OpenCode Go`,並貼上您的 API key。 +3. 在 TUI 中執行 `/models` 以查看透過 Go 可用的模型清單。 + +:::note +每個工作區只能有一位成員訂閱 OpenCode Go。 +::: + +目前的模型清單包括: + +- **GLM-5** +- **Kimi K2.5** +- **MiniMax M2.5** + +模型清單可能會隨著我們測試和新增模型而變動。 + +--- + +## 使用限制 + +OpenCode Go 包含以下限制: + +- **5 小時限制** — 12 美元的使用量 +- **每週限制** — 30 美元的使用量 +- **每月限制** — 60 美元的使用量 + +限制是以美元價值定義的。這意味著您的實際請求次數取決於您使用的模型。較便宜的模型(如 MiniMax M2.5)允許更多請求,而較高成本的模型(如 GLM-5)允許較少請求。 + +下表根據典型的 Go 使用模式提供估計的請求次數: + +| | GLM-5 | Kimi K2.5 | MiniMax M2.5 | +| --------------- | ----- | --------- | ------------ | +| 每 5 小時請求數 | 1,150 | 1,850 | 30,000 | +| 每週請求數 | 2,880 | 4,630 | 75,000 | +| 每月請求數 | 5,750 | 9,250 | 150,000 | + +估計值是根據觀察到的平均請求模式: + +- GLM-5 — 700 輸入, 52,000 快取, 150 輸出 token (每個請求) +- Kimi K2.5 — 870 輸入, 55,000 快取, 200 輸出 token (每個請求) +- MiniMax M2.5 — 300 輸入, 55,000 快取, 125 輸出 token (每個請求) + +您可以在 **console** 中追蹤目前的使用量。 + +:::tip +如果您達到使用限制,您可以繼續使用免費模型。 +::: + +使用限制可能會隨著我們從早期使用和回饋中學習而變動。 + +--- + +### 定價 + +OpenCode Go 是一個 **每月 10 美元** 的訂閱方案。以下是 **每 100 萬 token** 的價格。 + +| 模型 | 輸入 | 輸出 | 快取讀取 | +| ------------ | ----- | ----- | -------- | +| GLM-5 | $1.00 | $3.20 | $0.20 | +| Kimi K2.5 | $0.60 | $3.00 | $0.10 | +| MiniMax M2.5 | $0.30 | $1.20 | $0.03 | + +--- + +### 超出限制的使用 + +如果您的 Zen 餘額中也有點數,您可以在 console 中啟用 **Use balance** 選項。啟用後,當您達到使用限制時,Go 將會改用您的 Zen 餘額,而不是封鎖請求。 + +--- + +## 端點 + +您也可以透過以下 API 端點存取 Go 模型。 + +| 模型 | Model ID | 端點 | AI SDK 套件 | +| ------------ | ------------ | ------------------------------------------------ | --------------------------- | +| GLM-5 | glm-5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/go/v1/chat/completions` | `@ai-sdk/openai-compatible` | +| MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/go/v1/messages` | `@ai-sdk/anthropic` | + +您 OpenCode 設定中的 [model id](/docs/config/#models) 使用 `opencode-go/` 格式。例如,對於 Kimi K2.5,您會在設定中使用 `opencode-go/kimi-k2.5`。 + +--- + +## 隱私權 + +此方案主要是為國際使用者設計,模型託管在美國、歐盟和新加坡,以提供穩定的全球存取。 + +如果您有任何問題,請 聯絡我們。 + +--- + +## 目標 + +我們建立 OpenCode Go 是為了: + +1. 透過低成本訂閱,讓更多人能 **輕易取得** AI 程式設計資源。 +2. 提供對最佳開放程式設計模型的 **可靠** 存取。 +3. 策劃經過 **測試和基準測試** 的模型,以供程式設計代理使用。 +4. **沒有鎖定**,允許您在 OpenCode 中同時使用任何其他供應商。 diff --git a/packages/web/src/content/docs/zh-tw/keybinds.mdx b/packages/web/src/content/docs/zh-tw/keybinds.mdx index d1458dfe8c..ca085db01d 100644 --- a/packages/web/src/content/docs/zh-tw/keybinds.mdx +++ b/packages/web/src/content/docs/zh-tw/keybinds.mdx @@ -3,11 +3,11 @@ title: 快捷鍵 description: 自訂您的快捷鍵。 --- -OpenCode 提供了一系列快捷鍵,您可以透過 OpenCode 設定進行自訂。 +OpenCode 提供了一系列快捷鍵,您可以透過 `tui.json` 進行自訂。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "leader": "ctrl+x", "app_exit": "ctrl+c,ctrl+d,q", @@ -117,11 +117,11 @@ OpenCode 的大多數快捷鍵使用 `leader`(前導鍵)。這可以避免 ## 停用快捷鍵 -您可以透過在設定中將對應的鍵值設定為 "none" 來停用某個快捷鍵。 +您可以透過在 `tui.json` 中將對應的鍵值設定為 "none" 來停用某個快捷鍵。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "keybinds": { "session_compact": "none" } diff --git a/packages/web/src/content/docs/zh-tw/lsp.mdx b/packages/web/src/content/docs/zh-tw/lsp.mdx index ae419261ff..aa3af32881 100644 --- a/packages/web/src/content/docs/zh-tw/lsp.mdx +++ b/packages/web/src/content/docs/zh-tw/lsp.mdx @@ -27,6 +27,7 @@ OpenCode 內建了多種適用於主流語言的 LSP 伺服器: | gopls | .go | 需要 `go` 指令可用 | | hls | .hs, .lhs | 需要 `haskell-language-server-wrapper` 指令可用 | | jdtls | .java | 需要已安裝 `Java SDK (version 21+)` | +| julials | .jl | 需要已安裝 `julia` 和 `LanguageServer.jl` | | kotlin-ls | .kt, .kts | 為 Kotlin 專案自動安裝 | | lua-ls | .lua | 為 Lua 專案自動安裝 | | nixd | .nix | 需要 `nixd` 指令可用 | diff --git a/packages/web/src/content/docs/zh-tw/plugins.mdx b/packages/web/src/content/docs/zh-tw/plugins.mdx index 5e84f3a353..8163c291e0 100644 --- a/packages/web/src/content/docs/zh-tw/plugins.mdx +++ b/packages/web/src/content/docs/zh-tw/plugins.mdx @@ -307,6 +307,10 @@ export const CustomToolsPlugin: Plugin = async (ctx) => { 您的自訂工具將與內建工具一起在 OpenCode 中可用。 +:::note +如果外掛工具使用與內建工具相同的名稱,則外掛工具具有優先權。 +::: + --- ### 日誌記錄 diff --git a/packages/web/src/content/docs/zh-tw/providers.mdx b/packages/web/src/content/docs/zh-tw/providers.mdx index 12c4ded4e3..b673b1ade5 100644 --- a/packages/web/src/content/docs/zh-tw/providers.mdx +++ b/packages/web/src/content/docs/zh-tw/providers.mdx @@ -55,7 +55,7 @@ OpenCode Zen 是由 OpenCode 團隊提供的模型列表,這些模型已經過 如果您是新使用者,我們建議從 OpenCode Zen 開始。 ::: -1. 在 TUI 中執行 `/connect` 指令,選擇 opencode,然後前往 [opencode.ai/auth](https://opencode.ai/auth)。 +1. 在 TUI 中執行 `/connect` 指令,選擇 `OpenCode Zen`,然後前往 [opencode.ai/auth](https://opencode.ai/zen)。 ```txt /connect @@ -82,6 +82,37 @@ OpenCode Zen 是由 OpenCode 團隊提供的模型列表,這些模型已經過 --- +## OpenCode Go + +OpenCode Go 是一個低成本的訂閱計畫,提供對 OpenCode 團隊提供的流行開放編碼模型的可靠存取,這些模型已經過測試和驗證,能夠與 OpenCode 良好配合使用。 + +1. 在 TUI 中執行 `/connect` 指令,選擇 `OpenCode Go`,然後前往 [opencode.ai/auth](https://opencode.ai/zen)。 + + ```txt + /connect + ``` + +2. 登入後新增帳單資訊,然後複製您的 API 金鑰。 + +3. 貼上您的 API 金鑰。 + + ```txt + ┌ API key + │ + │ + └ enter + ``` + +4. 在 TUI 中執行 `/models` 查看我們推薦的模型列表。 + + ```txt + /models + ``` + +它的使用方式與 OpenCode 中的任何其他提供商相同,且完全可選。 + +--- + ## 目錄 下面我們來詳細了解一些提供商。如果您想將某個提供商新增到列表中,歡迎提交 PR。 diff --git a/packages/web/src/content/docs/zh-tw/themes.mdx b/packages/web/src/content/docs/zh-tw/themes.mdx index 513f2c8a77..256b78ccb6 100644 --- a/packages/web/src/content/docs/zh-tw/themes.mdx +++ b/packages/web/src/content/docs/zh-tw/themes.mdx @@ -61,11 +61,11 @@ OpenCode 自帶多個內建主題。 ## 使用主題 -您可以透過 `/theme` 指令調出主題選擇介面來選擇主題,也可以在[設定](/docs/config)檔案中直接指定。 +您可以透過 `/theme` 指令調出主題選擇介面來選擇主題,也可以在 `tui.json` 中直接指定。 -```json title="opencode.json" {3} +```json title="tui.json" {3} { - "$schema": "https://opencode.ai/config.json", + "$schema": "https://opencode.ai/tui.json", "theme": "tokyonight" } ``` diff --git a/packages/web/src/content/docs/zh-tw/tui.mdx b/packages/web/src/content/docs/zh-tw/tui.mdx index 017507f20e..8f46c4c15b 100644 --- a/packages/web/src/content/docs/zh-tw/tui.mdx +++ b/packages/web/src/content/docs/zh-tw/tui.mdx @@ -352,24 +352,34 @@ How is auth handled in @packages/functions/src/api/index.ts? ## 設定 -您可以透過 OpenCode 設定檔自訂 TUI 行為。 +您可以透過 `tui.json`(或 `tui.jsonc`)自訂 TUI 行為。 -```json title="opencode.json" +```json title="tui.json" { - "$schema": "https://opencode.ai/config.json", - "tui": { - "scroll_speed": 3, - "scroll_acceleration": { - "enabled": true - } - } + "$schema": "https://opencode.ai/tui.json", + "theme": "opencode", + "keybinds": { + "leader": "ctrl+x" + }, + "scroll_speed": 3, + "scroll_acceleration": { + "enabled": true + }, + "diff_style": "auto" } ``` +這與設定伺服器/執行時行為的 `opencode.json` 是分開的。 + ### 選項 -- `scroll_acceleration` - 啟用 macOS 風格的捲動加速,實現平滑、自然的捲動體驗。啟用後,快速捲動時速度會增加,慢速移動時保持精確。**此設定優先於 `scroll_speed`,啟用時會覆蓋它。** -- `scroll_speed` - 控制使用捲動指令時 TUI 的捲動速度(最小值:`1`)。預設為 `3`。**注意:如果 `scroll_acceleration.enabled` 設定為 `true`,則此設定會被忽略。** +- `theme` - 設定您的 UI 主題。[了解更多](/docs/themes)。 +- `keybinds` - 自訂鍵盤快速鍵。[了解更多](/docs/keybinds)。 +- `scroll_acceleration.enabled` - 啟用 macOS 風格的捲動加速,實現平滑、自然的捲動體驗。啟用後,快速捲動時速度會增加,慢速移動時保持精確。**此設定優先於 `scroll_speed`,啟用時會覆蓋它。** +- `scroll_speed` - 控制使用捲動指令時 TUI 的捲動速度(最小值:`0.001`,支援小數值)。預設為 `3`。**注意:如果 `scroll_acceleration.enabled` 設定為 `true`,則此設定會被忽略。** +- `diff_style` - 控制差異呈現方式。`"auto"` 根據終端機寬度自適應,`"stacked"` 始終顯示單列。 + +使用 `OPENCODE_TUI_CONFIG` 載入自訂 TUI 設定路徑。 --- diff --git a/packages/web/src/content/docs/zh-tw/zen.mdx b/packages/web/src/content/docs/zh-tw/zen.mdx index 5216194a93..c38188280b 100644 --- a/packages/web/src/content/docs/zh-tw/zen.mdx +++ b/packages/web/src/content/docs/zh-tw/zen.mdx @@ -55,6 +55,7 @@ OpenCode Zen 的工作方式與 OpenCode 中的任何其他供應商相同。 | 模型 | 模型 ID | 端點 | AI SDK 套件 | | ------------------ | ------------------ | -------------------------------------------------- | --------------------------- | +| GPT 5.3 Codex | gpt-5.3-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | @@ -64,13 +65,15 @@ OpenCode Zen 的工作方式與 OpenCode 中的任何其他供應商相同。 | GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | | GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` | +| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Claude Sonnet 4.6 | claude-sonnet-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | | Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | -| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` | +| Gemini 3.1 Pro | gemini-3.1-pro | `https://opencode.ai/zen/v1/models/gemini-3.1-pro` | `@ai-sdk/google` | | Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` | | Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` | | MiniMax M2.5 | minimax-m2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -80,7 +83,6 @@ OpenCode Zen 的工作方式與 OpenCode 中的任何其他供應商相同。 | GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | -| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | | Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` | @@ -113,24 +115,28 @@ https://opencode.ai/zen/v1/models | GLM 5 | $1.00 | $3.20 | $0.20 | - | | GLM 4.7 | $0.60 | $2.20 | $0.10 | - | | GLM 4.6 | $0.60 | $2.20 | $0.10 | - | -| Kimi K2.5 Free | 免費 | 免費 | 免費 | - | | Kimi K2.5 | $0.60 | $3.00 | $0.08 | - | | Kimi K2 Thinking | $0.40 | $2.50 | - | - | | Kimi K2 | $0.40 | $2.50 | - | - | | Qwen3 Coder 480B | $0.45 | $1.50 | - | - | +| Claude Opus 4.6 (≤ 200K Token) | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.6 (> 200K Token) | $10.00 | $37.50 | $1.00 | $12.50 | +| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | +| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Claude Sonnet 4.6 (≤ 200K Token) | $3.00 | $15.00 | $0.30 | $3.75 | +| Claude Sonnet 4.6 (> 200K Token) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4.5 (≤ 200K Token) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4.5 (> 200K Token) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Sonnet 4 (≤ 200K Token) | $3.00 | $15.00 | $0.30 | $3.75 | | Claude Sonnet 4 (> 200K Token) | $6.00 | $22.50 | $0.60 | $7.50 | | Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 | | Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 | -| Claude Opus 4.6 (≤ 200K Token) | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.6 (> 200K Token) | $10.00 | $37.50 | $1.00 | $12.50 | -| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 | -| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 | +| Gemini 3.1 Pro (≤ 200K Token) | $2.00 | $12.00 | $0.20 | - | +| Gemini 3.1 Pro (> 200K Token) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Pro (≤ 200K Token) | $2.00 | $12.00 | $0.20 | - | | Gemini 3 Pro (> 200K Token) | $4.00 | $18.00 | $0.40 | - | | Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - | +| GPT 5.3 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 | $1.75 | $14.00 | $0.175 | - | | GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - | | GPT 5.1 | $1.07 | $8.50 | $0.107 | - | @@ -149,7 +155,6 @@ https://opencode.ai/zen/v1/models 免費模型說明: -- Kimi K2.5 Free 在 OpenCode 上限時免費提供。團隊正在利用這段時間收集回饋並改進模型。 - MiniMax M2.5 Free 在 OpenCode 上限時免費提供。團隊正在利用這段時間收集回饋並改進模型。 - Big Pickle 是一個隱身模型,在 OpenCode 上限時免費提供。團隊正在利用這段時間收集回饋並改進模型。 @@ -178,7 +183,6 @@ https://opencode.ai/zen/v1/models 我們所有的模型都託管在美國。我們的供應商遵循零保留政策,不會將你的資料用於模型訓練,但以下情況除外: - Big Pickle:在免費期間,收集的資料可能會被用於改進模型。 -- Kimi K2.5 Free:在免費期間,收集的資料可能會被用於改進模型。 - MiniMax M2.5 Free:在免費期間,收集的資料可能會被用於改進模型。 - OpenAI API:請求會根據 [OpenAI 資料政策](https://platform.openai.com/docs/guides/your-data)保留 30 天。 - Anthropic API:請求會根據 [Anthropic 資料政策](https://docs.anthropic.com/en/docs/claude-code/data-usage)保留 30 天。 diff --git a/script/publish.ts b/script/publish.ts index 334a734922..3889845fa6 100755 --- a/script/publish.ts +++ b/script/publish.ts @@ -68,6 +68,7 @@ if (Script.release) { } await import(`../packages/desktop/scripts/finalize-latest-json.ts`) + await import(`../packages/desktop-electron/scripts/finalize-latest-yml.ts`) await $`gh release edit v${Script.version} --draft=false --repo ${process.env.GH_REPO}` } diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index a041b65223..69c586186a 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "1.2.15", + "version": "1.2.16", "publisher": "sst-dev", "repository": { "type": "git", diff --git a/specs/file-component-unification-plan.md b/specs/file-component-unification-plan.md deleted file mode 100644 index d63d665fd5..0000000000 --- a/specs/file-component-unification-plan.md +++ /dev/null @@ -1,426 +0,0 @@ -# File Component Unification Plan - -Single path for text, diff, and media - ---- - -## Define goal - -Introduce one public UI component API that renders plain text files or diffs from the same entry point, so selection, comments, search, theming, and media behavior are maintained once. - -### Goal - -- Add a unified `File` component in `packages/ui/src/components/file.tsx` that chooses plain or diff rendering from props. -- Centralize shared behavior now split between `packages/ui/src/components/code.tsx` and `packages/ui/src/components/diff.tsx`. -- Bring the existing find/search UX to diff rendering through a shared engine. -- Consolidate media rendering logic currently split across `packages/ui/src/components/session-review.tsx` and `packages/app/src/pages/session/file-tabs.tsx`. -- Provide a clear SSR path for preloaded diffs without keeping a third independent implementation. - -### Non-goal - -- Do not change `@pierre/diffs` behavior or fork its internals. -- Do not redesign line comment UX, diff visuals, or keyboard shortcuts. -- Do not remove legacy `Code`/`Diff` APIs in the first pass. -- Do not add new media types beyond parity unless explicitly approved. -- Do not refactor unrelated session review or file tab layout code outside integration points. - ---- - -## Audit duplication - -The current split duplicates runtime logic and makes feature parity drift likely. - -### Duplicate categories - -- Rendering lifecycle is duplicated in `code.tsx` and `diff.tsx`, including instance creation, cleanup, `onRendered` readiness, and shadow root lookup. -- Theme sync is duplicated in `code.tsx`, `diff.tsx`, and `diff-ssr.tsx` through similar `applyScheme` and `MutationObserver` code. -- Line selection wiring is duplicated in `code.tsx` and `diff.tsx`, including drag state, shadow selection reads, and line-number bridge integration. -- Comment annotation rerender flow is duplicated in `code.tsx`, `diff.tsx`, and `diff-ssr.tsx`. -- Commented line marking is split across `markCommentedFileLines` and `markCommentedDiffLines`, with similar timing and effect wiring. -- Diff selection normalization (`fixSelection`) exists twice in `diff.tsx` and `diff-ssr.tsx`. -- Search exists only in `code.tsx`, so diff lacks find and the feature cannot be maintained in one place. -- Contexts are split (`context/code.tsx`, `context/diff.tsx`), which forces consumers to choose paths early. -- Media rendering is duplicated outside the core viewers in `session-review.tsx` and `file-tabs.tsx`. - -### Drift pain points - -- Any change to comments, theming, or selection requires touching multiple files. -- Diff SSR and client diff can drift because they carry separate normalization and marking code. -- Search cannot be added to diff cleanly without more duplication unless the viewer runtime is unified. - ---- - -## Design architecture - -Use one public component with a discriminated prop shape and split shared behavior into small runtime modules. - -### Public API proposal - -- Add `packages/ui/src/components/file.tsx` as the primary client entry point. -- Export a single `File` component that accepts a discriminated union with two primary modes. -- Use an explicit `mode` prop (`"text"` or `"diff"`) to avoid ambiguous prop inference and keep type errors clear. - -### Proposed prop shape - -- Shared props: - - `annotations` - - `selectedLines` - - `commentedLines` - - `onLineSelected` - - `onLineSelectionEnd` - - `onLineNumberSelectionEnd` - - `onRendered` - - `class` - - `classList` - - selection and hover flags already supported by current viewers -- Text mode props: - - `mode: "text"` - - `file` (`FileContents`) - - text renderer options from `@pierre/diffs` `FileOptions` -- Diff mode props: - - `mode: "diff"` - - `before` - - `after` - - `diffStyle` - - diff renderer options from `FileDiffOptions` - - optional `preloadedDiff` only for SSR-aware entry or hydration adapter -- Media props (shared, optional): - - `media` config for `"auto" | "off"` behavior - - path/name metadata - - optional lazy loader (`readFile`) for session review use - - optional custom placeholders for binary or removed content - -### Internal module split - -- `packages/ui/src/components/file.tsx` - Public unified component and mode routing. -- `packages/ui/src/components/file-ssr.tsx` - Unified SSR entry for preloaded diff hydration. -- `packages/ui/src/components/file-search.tsx` - Shared find bar UI and host registration. -- `packages/ui/src/components/file-media.tsx` - Shared image/audio/svg/binary rendering shell. -- `packages/ui/src/pierre/file-runtime.ts` - Common render lifecycle, instance setup, cleanup, scheme sync, and readiness notification. -- `packages/ui/src/pierre/file-selection.ts` - Shared selection/drag/line-number bridge controller with mode adapters. -- `packages/ui/src/pierre/diff-selection.ts` - Diff-specific `fixSelection` and row/side normalization reused by client and SSR. -- `packages/ui/src/pierre/file-find.ts` - Shared find engine (scan, highlight API, overlay fallback, match navigation). -- `packages/ui/src/pierre/media.ts` - MIME normalization, data URL helpers, and media type detection. - -### Wrapper strategy - -- Keep `packages/ui/src/components/code.tsx` as a thin compatibility wrapper over unified `File` in text mode. -- Keep `packages/ui/src/components/diff.tsx` as a thin compatibility wrapper over unified `File` in diff mode. -- Keep `packages/ui/src/components/diff-ssr.tsx` as a thin compatibility wrapper over unified SSR entry. - ---- - -## Phase delivery - -Ship this in small phases so each step is reviewable and reversible. - -### Phase 0: Align interfaces - -- Document the final prop contract and adapter behavior before moving logic. -- Add a short migration note in the plan PR description so reviewers know wrappers stay in place. - -#### Acceptance - -- Final prop names and mode shape are agreed up front. -- No runtime code changes land yet. - -### Phase 1: Extract shared runtime pieces - -- Move duplicated theme sync and render readiness logic from `code.tsx` and `diff.tsx` into shared runtime helpers. -- Move diff selection normalization (`fixSelection` and helpers) out of both `diff.tsx` and `diff-ssr.tsx` into `packages/ui/src/pierre/diff-selection.ts`. -- Extract shared selection controller flow into `packages/ui/src/pierre/file-selection.ts` with mode callbacks for line parsing and normalization. -- Keep `code.tsx`, `diff.tsx`, and `diff-ssr.tsx` behavior unchanged from the outside. - -#### Acceptance - -- `code.tsx`, `diff.tsx`, and `diff-ssr.tsx` are smaller and call shared helpers. -- Line selection, comments, and theme sync still work in current consumers. -- No consumer imports change yet. - -### Phase 2: Introduce unified client entry - -- Create `packages/ui/src/components/file.tsx` and wire it to shared runtime pieces. -- Route text mode to `@pierre/diffs` `File` or `VirtualizedFile` and diff mode to `FileDiff` or `VirtualizedFileDiff`. -- Preserve current performance rules, including virtualization thresholds and large-diff options. -- Keep search out of this phase if it risks scope creep, but leave extension points in place. - -#### Acceptance - -- New unified component renders text and diff with parity to existing components. -- `code.tsx` and `diff.tsx` can be rewritten as thin adapters without behavior changes. -- Existing consumers still work through old `Code` and `Diff` exports. - -### Phase 3: Add unified context path - -- Add `packages/ui/src/context/file.tsx` with `FileComponentProvider` and `useFileComponent`. -- Update `packages/ui/src/context/index.ts` to export the new context. -- Keep `context/code.tsx` and `context/diff.tsx` as compatibility shims that adapt to `useFileComponent`. -- Migrate `packages/app/src/app.tsx` and `packages/enterprise/src/routes/share/[shareID].tsx` to provide the unified component once wrappers are stable. - -#### Acceptance - -- New consumers can use one context path. -- Existing `useCodeComponent` and `useDiffComponent` hooks still resolve and render correctly. -- Provider wiring in app and enterprise stays compatible during transition. - -### Phase 4: Share find and enable diff search - -- Extract the find engine and find bar UI from `code.tsx` into shared modules. -- Hook the shared find host into unified `File` for both text and diff modes. -- Keep current shortcuts (`Ctrl/Cmd+F`, `Ctrl/Cmd+G`, `Shift+Ctrl/Cmd+G`) and active-host behavior. -- Preserve CSS Highlight API support with overlay fallback. - -#### Acceptance - -- Text mode search behaves the same as today. -- Diff mode now supports the same find UI and shortcuts. -- Multiple viewer instances still route shortcuts to the focused/active host correctly. - -### Phase 5: Consolidate media rendering - -- Extract media type detection and data URL helpers from `session-review.tsx` and `file-tabs.tsx` into shared UI helpers. -- Add `file-media.tsx` and let unified `File` optionally render media or binary placeholders before falling back to text/diff. -- Migrate `session-review.tsx` and `file-tabs.tsx` to pass media props instead of owning media-specific branches. -- Keep session-specific layout and i18n strings in the consumer where they are not generic. - -#### Acceptance - -- Image/audio/svg/binary handling no longer duplicates core detection and load state logic. -- Session review and file tabs still render the same media states and placeholders. -- Text/diff comment and selection behavior is unchanged when media is not shown. - -### Phase 6: Align SSR and preloaded diffs - -- Create `packages/ui/src/components/file-ssr.tsx` with the same unified prop shape plus `preloadedDiff`. -- Reuse shared diff normalization, theme sync, and commented-line marking helpers. -- Convert `packages/ui/src/components/diff-ssr.tsx` into a thin adapter that forwards to the unified SSR entry in diff mode. -- Migrate enterprise share page imports to `@opencode-ai/ui/file-ssr` when convenient, but keep `diff-ssr` export working. - -#### Acceptance - -- Preloaded diff hydration still works in `packages/enterprise/src/routes/share/[shareID].tsx`. -- SSR diff and client diff now share normalization and comment marking helpers. -- No duplicate `fixSelection` implementation remains. - -### Phase 7: Clean up and document - -- Remove dead internal helpers left behind in `code.tsx` and `diff.tsx`. -- Add a short migration doc for downstream consumers that want to switch from `Code`/`Diff` to unified `File`. -- Mark `Code`/`Diff` contexts and components as compatibility APIs in comments or docs. - -#### Acceptance - -- No stale duplicate helpers remain in legacy wrappers. -- Unified path is the default recommendation for new UI work. - ---- - -## Preserve compatibility - -Keep old APIs working while moving internals under them. - -### Context migration strategy - -- Introduce `FileComponentProvider` without deleting `CodeComponentProvider` or `DiffComponentProvider`. -- Implement `useCodeComponent` and `useDiffComponent` as adapters around the unified context where possible. -- If full adapter reuse is messy at first, keep old contexts and providers as thin wrappers that internally provide mapped unified props. - -### Consumer migration targets - -- `packages/app/src/pages/session/file-tabs.tsx` should move from `useCodeComponent` to `useFileComponent`. -- `packages/ui/src/components/session-review.tsx`, `session-turn.tsx`, and `message-part.tsx` should move from `useDiffComponent` to `useFileComponent`. -- `packages/app/src/app.tsx` and `packages/enterprise/src/routes/share/[shareID].tsx` should eventually provide only the unified provider. -- Keep legacy hooks available until all call sites are migrated and reviewed. - -### Compatibility checkpoints - -- `@opencode-ai/ui/code`, `@opencode-ai/ui/diff`, and `@opencode-ai/ui/diff-ssr` imports must keep working during migration. -- Existing prop names on `Code` and `Diff` wrappers should remain stable to avoid broad app changes in one PR. - ---- - -## Unify search - -Port the current find feature into a shared engine and attach it to both modes. - -### Shared engine plan - -- Move keyboard host registry and active-target logic out of `code.tsx` into `packages/ui/src/pierre/file-find.ts`. -- Move the find bar UI into `packages/ui/src/components/file-search.tsx`. -- Keep DOM-based scanning and highlight/overlay rendering shared, since both text and diff render into the same shadow-root patterns. - -### Diff-specific handling - -- Search should scan both unified and split diff columns through the same selectors used in the current code find feature. -- Match navigation should scroll the active range into view without interfering with line selection state. -- Search refresh should run after `onRendered`, diff style changes, annotation rerenders, and query changes. - -### Scope guard - -- Preserve the current DOM-scan behavior first, even if virtualized search is limited to mounted rows. -- If full-document virtualized search is required, treat it as a follow-up with a text-index layer rather than blocking the core refactor. - ---- - -## Consolidate media - -Move media rendering logic into shared UI so text, diff, and media routing live behind one entry. - -### Ownership plan - -- Put media detection and normalization helpers in `packages/ui/src/pierre/media.ts`. -- Put shared rendering UI in `packages/ui/src/components/file-media.tsx`. -- Keep layout-specific wrappers in `session-review.tsx` and `file-tabs.tsx`, but remove duplicated media branching and load-state code from them. - -### Proposed media props - -- `media.mode`: `"auto"` or `"off"` for default behavior. -- `media.path`: file path for extension checks and labels. -- `media.current`: loaded file content for plain-file views. -- `media.before` and `media.after`: diff-side values for image/audio previews. -- `media.readFile`: optional lazy loader for session review expansion. -- `media.renderBinaryPlaceholder`: optional consumer override for binary states. -- `media.renderLoading` and `media.renderError`: optional consumer overrides when generic text is not enough. - -### Parity targets - -- Keep current image and audio support from session review. -- Keep current SVG and binary handling from file tabs. -- Defer video or PDF support unless explicitly requested. - ---- - -## Align SSR - -Make SSR diff hydration a mode of the unified viewer instead of a parallel implementation. - -### SSR plan - -- Add `packages/ui/src/components/file-ssr.tsx` as the unified SSR entry with a diff-only path in phase one. -- Reuse shared diff helpers for `fixSelection`, theme sync, and commented-line marking. -- Keep the private `fileContainer` hydration workaround isolated in the SSR module so client code stays clean. - -### Integration plan - -- Keep `packages/ui/src/components/diff-ssr.tsx` as a forwarding adapter for compatibility. -- Update enterprise share route to the unified SSR import after client and context migrations are stable. -- Align prop names with the client `File` component so `SessionReview` can swap client/SSR providers without branching logic. - -### Defer item - -- Plain-file SSR hydration is not needed for this refactor and can stay out of scope. - ---- - -## Verify behavior - -Use typechecks and targeted UI checks after each phase, and avoid repo-root runs. - -### Typecheck plan - -- Run `bun run typecheck` from `packages/ui` after phases 1-7 changes there. -- Run `bun run typecheck` from `packages/app` after migrating file tabs or app provider wiring. -- Run `bun run typecheck` from `packages/enterprise` after SSR/provider changes on the share route. - -### Targeted UI checks - -- Text mode: - - small file render - - virtualized large file render - - drag selection and line-number selection - - comment annotations and commented-line marks - - find shortcuts and match navigation -- Diff mode: - - unified and split styles - - large diff fallback options - - diff selection normalization across sides - - comments and commented-line marks - - new find UX parity -- Media: - - image, audio, SVG, and binary states in file tabs - - image and audio diff previews in session review - - lazy load and error placeholders -- SSR: - - enterprise share page preloaded diffs hydrate correctly - - theme switching still updates hydrated diffs - -### Regression focus - -- Watch scroll restore behavior in `packages/app/src/pages/session/file-tabs.tsx`. -- Watch multi-instance find shortcut routing in screens with many viewers. -- Watch cleanup paths for listeners and virtualizers to avoid leaks. - ---- - -## Manage risk - -Keep wrappers and adapters in place until the unified path is proven. - -### Key risks - -- Selection regressions are the highest risk because text and diff have similar but not identical line semantics. -- SSR hydration can break subtly if client and SSR prop shapes drift. -- Shared find host state can misroute shortcuts when many viewers are mounted. -- Media consolidation can accidentally change placeholder timing or load behavior. - -### Rollback strategy - -- Land each phase in separate PRs or clearly separated commits on `dev`. -- If a phase regresses behavior, revert only that phase and keep earlier extractions. -- Keep `code.tsx`, `diff.tsx`, and `diff-ssr.tsx` wrappers intact until final verification, so a rollback only changes internals. -- If diff search is unstable, disable it behind the unified component while keeping the rest of the refactor. - ---- - -## Order implementation - -Follow this sequence to keep reviews small and reduce merge risk. - -1. Finalize prop shape and file names for the unified component and context. -2. Extract shared diff normalization, theme sync, and render-ready helpers with no public API changes. -3. Extract shared selection controller and migrate `code.tsx` and `diff.tsx` to it. -4. Add the unified client `File` component and convert `code.tsx`/`diff.tsx` into wrappers. -5. Add `FileComponentProvider` and migrate provider wiring in `app.tsx` and enterprise share route. -6. Migrate consumer hooks (`file-tabs`, `session-review`, `message-part`, `session-turn`) to the unified context. -7. Extract and share find engine/UI, then enable search in diff mode. -8. Extract media helpers/UI and migrate `session-review.tsx` and `file-tabs.tsx`. -9. Add unified `file-ssr.tsx`, convert `diff-ssr.tsx` to a wrapper, and migrate enterprise imports. -10. Remove dead duplication and write a short migration note for future consumers. - ---- - -## Decide open items - -Resolve these before coding to avoid rework mid-refactor. - -### API decisions - -- Should the unified component require `mode`, or should it infer mode from props for convenience. -- Should the public export be named `File` only, or also ship a temporary alias like `UnifiedFile` for migration clarity. -- Should `preloadedDiff` live on the main `File` props or only on `file-ssr.tsx`. - -### Search decisions - -- Is DOM-only search acceptable for virtualized content in the first pass. -- Should find state reset on every rerender, or preserve query and index across diff style toggles. - -### Media decisions - -- Which placeholders and strings should stay consumer-owned versus shared in UI. -- Whether SVG should be treated as media-only, text-only, or a mixed mode with both preview and source. -- Whether video support should be included now or explicitly deferred. - -### Migration decisions - -- How long `CodeComponentProvider` and `DiffComponentProvider` should remain supported. -- Whether to migrate all consumers in one PR after wrappers land, or in follow-up PRs by surface area. -- Whether `diff-ssr` should remain as a permanent alias for compatibility. diff --git a/specs/session-composer-refactor-plan.md b/specs/session-composer-refactor-plan.md deleted file mode 100644 index 08fb0d8323..0000000000 --- a/specs/session-composer-refactor-plan.md +++ /dev/null @@ -1,240 +0,0 @@ -# Session Composer Refactor Plan - -## Goal - -Improve structure, ownership, and reuse for the bottom-of-session composer area without changing user-visible behavior. - -Scope: - -- `packages/ui/src/components/dock-prompt.tsx` -- `packages/app/src/components/session-todo-dock.tsx` -- `packages/app/src/components/question-dock.tsx` -- `packages/app/src/pages/session/session-prompt-dock.tsx` -- related shared UI in `packages/app/src/components/prompt-input.tsx` - -## Decisions Up Front - -1. **`session-prompt-dock` should stay route-scoped.** - It is session-page orchestration, so it belongs under `pages/session`, not global `src/components`. - -2. **The orchestrator should keep blocking ownership.** - A single component should decide whether to show blockers (`question`/`permission`) or the regular prompt input. This avoids drift and duplicate logic. - -3. **Current component does too much.** - Split state derivation, permission actions, and rendering into smaller units while preserving behavior. - -4. **There is style duplication worth addressing.** - The prompt top shell and lower tray (`prompt-input.tsx`) visually overlap with dock shells/footers and todo containers. We should extract reusable dock surface primitives. - ---- - -## Phase 0 (Mandatory Gate): Baseline E2E Coverage - -No refactor work starts until this phase is complete and green locally. - -### 0.1 Deterministic test harness - -Add a test-only way to put a session into exact dock states, so tests do not rely on model/tool nondeterminism. - -Proposed implementation: - -- Add a guarded e2e route in backend (enabled only when a dedicated env flag is set by e2e-local runner). - - New route file: `packages/opencode/src/server/routes/e2e.ts` - - Mount from: `packages/opencode/src/server/server.ts` - - Gate behind env flag (for example `OPENCODE_E2E=1`) so this route is never exposed in normal runs. -- Add seed helpers in app e2e layer: - - `packages/app/e2e/actions.ts` (or `fixtures.ts`) helpers to: - - seed question request for a session - - seed permission request for a session - - seed/update todos for a session - - clear seeded blockers/todos -- Update e2e-local runner to set the flag: - - `packages/app/script/e2e-local.ts` - -### 0.2 New e2e spec - -Create a focused spec: - -- `packages/app/e2e/session/session-composer-dock.spec.ts` - -Test matrix (minimum required): - -1. **Default prompt dock** - - no blocker state - - assert prompt input is visible and focusable - - assert blocker cards are absent - -2. **Blocked question flow** - - seed question request for session - - assert question dock renders - - assert prompt input is not shown/active - - answer and submit - - assert unblock and prompt input returns - -3. **Blocked permission flow** - - seed permission request with patterns + optional description - - assert permission dock renders expected actions - - assert prompt input is not shown/active - - test each response path (`once`, `always`, `reject`) across tests - - assert unblock behavior - -4. **Todo dock transitions and collapse behavior** - - seed todos with `pending`/`in_progress` - - assert todo dock appears above prompt and can collapse/expand - - update todos to all completed/cancelled - - assert close animation path and eventual hide - -5. **Keyboard focus behavior while blocked** - - with blocker active, typing from document context must not focus prompt input - - blocker actions remain keyboard reachable - -Notes: - -- Prefer stable selectors (`data-component`, `data-slot`, role/name). -- Extend `packages/app/e2e/selectors.ts` as needed. -- Use `expect.poll` for async transitions. - -### 0.3 Gate commands (must pass before Phase 1) - -Run from `packages/app` (never from repo root): - -```bash -bun test:e2e:local -- e2e/session/session-composer-dock.spec.ts -bun test:e2e:local -- e2e/prompt/prompt.spec.ts e2e/prompt/prompt-multiline.spec.ts e2e/commands/input-focus.spec.ts -bun test:e2e:local -``` - -If any fail, stop and fix before refactor. - ---- - -## Phase 1: Structural Refactor (No Intended Behavior Changes) - -### 1.1 Colocate session-composer files - -Create a route-local composer folder: - -```txt -packages/app/src/pages/session/composer/ - session-composer-region.tsx # rename/move from session-prompt-dock.tsx - session-composer-state.ts # derived state + actions - session-permission-dock.tsx # extracted from inline JSX - session-question-dock.tsx # moved from src/components/question-dock.tsx - session-todo-dock.tsx # moved from src/components/session-todo-dock.tsx - index.ts -``` - -Import updates: - -- `packages/app/src/pages/session.tsx` imports `SessionComposerRegion` from `pages/session/composer`. - -### 1.2 Split responsibilities - -- Keep `session-composer-region.tsx` focused on rendering orchestration: - - blocker mode vs normal mode - - relative stacking (todo above prompt) - - handoff fallback rendering -- Move side-effect/business pieces into `session-composer-state.ts`: - - derive `questionRequest`, `permissionRequest`, `blocked`, todo visibility state - - permission response action + in-flight state - - todo close/open animation state - -### 1.3 Remove duplicate blocked logic in `session.tsx` - -Current `session.tsx` computes `blocked` independently. Make the composer state the single source for blocker status consumed by both: - -- page-level keydown autofocus guard -- composer rendering guard - -### 1.4 Keep prompt gating in orchestrator - -`session-composer-region` should remain responsible for choosing whether `PromptInput` renders when blocked. - -Rationale: - -- this is layout-mode orchestration, not prompt implementation detail -- keeps blocker and prompt transitions coordinated in one place - -### 1.5 Phase 1 acceptance criteria - -- No intentional behavior deltas. -- Phase 0 suite remains green. -- `session-prompt-dock` no longer exists as a large mixed-responsibility component. -- Session composer files are colocated under `pages/session/composer`. - ---- - -## Phase 2: Reuse + Styling Maintainability - -### 2.1 Extract shared dock surface primitives - -Create reusable shell/tray wrappers to remove repeated visual scaffolding: - -- primary elevated surface (prompt top shell / dock body) -- secondary tray surface (prompt bottom bar / dock footer / todo shell) - -Proposed targets: - -- `packages/ui/src/components` for shared primitives if reused by both app and ui components -- or `packages/app/src/pages/session/composer` first, then promote to ui after proving reuse - -### 2.2 Apply primitives to current components - -Adopt in: - -- `packages/app/src/components/prompt-input.tsx` -- `packages/app/src/pages/session/composer/session-todo-dock.tsx` -- `packages/ui/src/components/dock-prompt.tsx` (where appropriate) - -Focus on deduping patterns seen in: - -- prompt elevated shell styles (`prompt-input.tsx` form container) -- prompt lower tray (`prompt-input.tsx` bottom panel) -- dock prompt footer/body and todo dock container - -### 2.3 De-risk style ownership - -- Move dock-specific styling out of overly broad files (for example, avoid keeping new dock-specific rules buried in unrelated message-part styling files). -- Keep slot names stable unless tests are updated in the same PR. - -### 2.4 Optional follow-up (if low risk) - -Evaluate extracting shared question/permission presentational pieces used by: - -- `packages/app/src/pages/session/composer/session-question-dock.tsx` -- `packages/ui/src/components/message-part.tsx` - -Only do this if behavior parity is protected by tests and the change is still reviewable. - -### 2.5 Phase 2 acceptance criteria - -- Reduced duplicated shell/tray styling code. -- No regressions in blocker/todo/prompt transitions. -- Phase 0 suite remains green. - ---- - -## Implementation Sequence (single branch) - -1. **Step A - Baseline safety net** - - Add e2e harness + new session composer dock spec + selector/helpers. - - Must pass locally before any refactor work proceeds. - -2. **Step B - Phase 1 colocation/splitting** - - Move/rename files, extract state and permission component, keep behavior. - -3. **Step C - Phase 1 dedupe blocked source** - - Remove duplicate blocked derivation and wire page autofocus guard to shared source. - -4. **Step D - Phase 2 style primitives** - - Introduce shared surface primitives and migrate prompt/todo/dock usage. - -5. **Step E (optional) - shared question/permission presentational extraction** - ---- - -## Rollback Strategy - -- Keep each step logically isolated and easy to revert. -- If regressions occur, revert the latest completed step first and rerun the Phase 0 suite. -- If style extraction destabilizes behavior, keep structural Phase 1 changes and revert only Phase 2 styling commits. diff --git a/specs/session-review-cross-diff-search-plan.md b/specs/session-review-cross-diff-search-plan.md deleted file mode 100644 index 6a15d5bec3..0000000000 --- a/specs/session-review-cross-diff-search-plan.md +++ /dev/null @@ -1,234 +0,0 @@ -# Session Review Cross-Diff Search Plan - -One search input for all diffs in the review pane - ---- - -## Goal - -Add a single search UI to `SessionReview` that searches across all diff files in the accordion and supports next/previous navigation across files. - -Navigation should auto-open the target accordion item and reveal the active match inside the existing unified `File` diff viewer. - ---- - -## Non-goals - -- Do not change diff rendering visuals, line comments, or file selection behavior. -- Do not add regex, fuzzy search, or replace. -- Do not change `@pierre/diffs` internals. - ---- - -## Current behavior - -- `SessionReview` renders one `File` diff viewer per accordion item, but only mounts the viewer when that item is expanded. -- Large diffs may be blocked behind the `MAX_DIFF_CHANGED_LINES` gate until the user clicks "render anyway". -- `File` owns a local search engine (`createFileFind`) with: - - query state - - hit counting - - current match index - - highlighting (CSS Highlight API or overlay fallback) - - `Cmd/Ctrl+F` and `Cmd/Ctrl+G` keyboard handling -- `FileSearchBar` is currently rendered per viewer. -- There is no parent-level search state in `SessionReview`. - ---- - -## UX requirements - -- Add one search bar in the `SessionReview` header (input, total count, prev, next, close). -- Show a global count like `3/17` across all searchable diffs. -- `Cmd/Ctrl+F` inside the session review pane opens the session-level search. -- `Cmd/Ctrl+G`, `Shift+Cmd/Ctrl+G`, `Enter`, and `Shift+Enter` navigate globally. -- Navigating to a match in a collapsed file auto-expands that file. -- The active match scrolls into view and is highlighted in the target viewer. -- Media/binary diffs are excluded from search. -- Empty query clears highlights and resets to `0/0`. - ---- - -## Architecture proposal - -Use a hybrid model: - -- A **session-level match index** for global searching/counting/navigation across all diffs. -- The existing **per-viewer search engine** for local highlighting and scrolling in the active file. - -This avoids mounting every accordion item just to search while reusing the existing DOM highlight behavior. - -### High-level pieces - -- `SessionReview` owns the global query, hit list, and active hit index. -- `File` exposes a small controlled search handle (register, set query, clear, reveal hit). -- `SessionReview` keeps a map of mounted file viewers and their search handles. -- `SessionReview` resolves next/prev hits, expands files as needed, then tells the target viewer to reveal the hit. - ---- - -## Data model and interfaces - -```ts -type SessionSearchHit = { - file: string - side: "additions" | "deletions" - line: number - col: number - len: number -} - -type SessionSearchState = { - query: string - hits: SessionSearchHit[] - active: number -} -``` - -```ts -type FileSearchReveal = { - side: "additions" | "deletions" - line: number - col: number - len: number -} - -type FileSearchHandle = { - setQuery: (value: string) => void - clear: () => void - reveal: (hit: FileSearchReveal) => boolean - refresh: () => void -} -``` - -```ts -type FileSearchControl = { - shortcuts?: "global" | "disabled" - showBar?: boolean - register: (handle: FileSearchHandle | null) => void -} -``` - ---- - -## Integration steps - -### Phase 1: Expose controlled search on `File` - -- Extend `createFileFind` and `File` to support a controlled search handle. -- Keep existing per-viewer search behavior as the default path. -- Add a way to disable per-viewer global shortcuts when hosted inside `SessionReview`. - -#### Acceptance - -- `File` still supports local search unchanged by default. -- `File` can optionally register a search handle and accept controlled reveal calls. - -### Phase 2: Add session-level search state in `SessionReview` - -- Add a single search UI in the `SessionReview` header (can reuse `FileSearchBar` visuals or extract shared presentational pieces). -- Build a global hit list from `props.diffs` string content. -- Index hits by file/side/line/column/length. - -#### Acceptance - -- Header search appears once for the pane. -- Global hit count updates as query changes. -- Media/binary diffs are excluded. - -### Phase 3: Wire global navigation to viewers - -- Register a `FileSearchHandle` per mounted diff viewer. -- On next/prev, resolve the active global hit and: - 1. expand the target file if needed - 2. wait for the viewer to mount/render - 3. call `handle.setQuery(query)` and `handle.reveal(hit)` - -#### Acceptance - -- Next/prev moves across files. -- Collapsed targets auto-open. -- Active match is highlighted in the target diff. - -### Phase 4: Handle large-diff gating - -- Lift `render anyway` state from local accordion item state into a file-keyed map in `SessionReview`. -- If navigation targets a gated file, force-render it before reveal. - -#### Acceptance - -- Global search can navigate into a large diff without manual user expansion/render. - -### Phase 5: Keyboard and race-condition polish - -- Route `Cmd/Ctrl+F`, `Cmd/Ctrl+G`, `Shift+Cmd/Ctrl+G` to session search when focus is in the review pane. -- Add token/cancel guards so fast navigation does not reveal stale targets after async mounts. - -#### Acceptance - -- Keyboard shortcuts consistently target session-level search. -- No stale reveal jumps during rapid navigation. - ---- - -## Edge cases - -- Empty query: clear all viewer highlights, reset count/index. -- No results: keep the search bar open, disable prev/next. -- Added/deleted files: index only the available side. -- Collapsed files: queue reveal until `onRendered` fires. -- Large diffs: auto-force render before reveal. -- Split diff mode: handle duplicate text on both sides without losing side info. -- Do not clear line comment draft or selected lines when navigating search results. - ---- - -## Testing plan - -### Unit tests - -- Session hit-index builder: - - line/column mapping - - additions/deletions side tagging - - wrap-around next/prev behavior -- `File` controlled search handle: - - `setQuery` - - `clear` - - `reveal` by side/line/column in unified and split diff - -### Component / integration tests - -- Search across multiple diffs and navigate across collapsed accordion items. -- Global counter updates correctly (`current/total`). -- Split and unified diff styles both navigate correctly. -- Large diff target auto-renders on navigation. -- Existing line comment draft remains intact while searching. - -### Manual verification - -- `Cmd/Ctrl+F` opens session-level search in the review pane. -- `Cmd/Ctrl+G` / `Shift+Cmd/Ctrl+G` navigate globally. -- Highlighting and scroll behavior stay stable with many open diffs. - ---- - -## Risks and rollback - -### Key risks - -- Global index and DOM highlights can drift if line/column mapping does not match viewer DOM content exactly. -- Keyboard shortcut conflicts between session-level search and per-viewer search. -- Performance impact when indexing many large diffs in one session. - -### Rollback plan - -- Gate session-level search behind a `SessionReview` prop/flag during rollout. -- If unstable, disable the session-level path and keep existing per-viewer search unchanged. - ---- - -## Open questions - -- Should search match file paths as well as content, or content only? -- In split mode, should the same text on both sides count as two matches? -- Should auto-navigation into gated large diffs silently render them, or show a prompt first? -- Should the session-level search bar reuse `FileSearchBar` directly or split out a shared non-portal variant? diff --git a/sst-env.d.ts b/sst-env.d.ts index fb7a7dc420..c8622a5a9a 100644 --- a/sst-env.d.ts +++ b/sst-env.d.ts @@ -145,10 +145,6 @@ declare module "sst" { "type": "sst.cloudflare.StaticSite" "url": string } - "ZEN_BLACK_LIMITS": { - "type": "sst.sst.Secret" - "value": string - } "ZEN_BLACK_PRICE": { "plan100": string "plan20": string @@ -156,7 +152,7 @@ declare module "sst" { "product": string "type": "sst.sst.Linkable" } - "ZEN_LITE_LIMITS": { + "ZEN_LIMITS": { "type": "sst.sst.Secret" "value": string } diff --git a/turbo.json b/turbo.json index ba3d01d360..f06ddb0e8b 100644 --- a/turbo.json +++ b/turbo.json @@ -3,9 +3,7 @@ "globalEnv": ["CI", "OPENCODE_DISABLE_SHARE"], "globalPassThroughEnv": ["CI", "OPENCODE_DISABLE_SHARE"], "tasks": { - "typecheck": { - "dependsOn": ["^build"] - }, + "typecheck": {}, "build": { "dependsOn": ["^build"], "outputs": ["dist/**"]